aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--.gitignore7
-rw-r--r--.travis.yml1
-rw-r--r--Makefile.am124
-rw-r--r--conformance/ConformanceJava.java120
-rw-r--r--conformance/Makefile.am31
-rw-r--r--conformance/conformance.proto1
-rw-r--r--conformance/conformance_test_runner.cc4
-rwxr-xr-xexamples/add_person.py2
-rwxr-xr-xexamples/list_people.py2
-rwxr-xr-xgenerate_descriptor_proto.sh1
-rw-r--r--javanano/README.md23
-rw-r--r--javanano/pom.xml15
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java2
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java264
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java28
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/Extension.java33
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/FieldArray.java34
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/FieldData.java52
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/InternalNano.java8
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/MessageNano.java8
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java4
-rw-r--r--javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java4
-rw-r--r--javanano/src/test/java/com/google/protobuf/nano/NanoTest.java80
-rw-r--r--javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto4
-rwxr-xr-xobjectivec/DevTools/check_version_stamps.sh56
-rwxr-xr-xobjectivec/DevTools/generate_descriptors_proto.sh36
-rwxr-xr-xobjectivec/DevTools/pddm.py687
-rwxr-xr-xobjectivec/DevTools/pddm_tests.py515
-rw-r--r--objectivec/GPBArray.h535
-rw-r--r--objectivec/GPBArray.m2499
-rw-r--r--objectivec/GPBArray_PackagePrivate.h130
-rw-r--r--objectivec/GPBBootstrap.h84
-rw-r--r--objectivec/GPBCodedInputStream.h81
-rw-r--r--objectivec/GPBCodedInputStream.m801
-rw-r--r--objectivec/GPBCodedInputStream_PackagePrivate.h131
-rw-r--r--objectivec/GPBCodedOutputStream.h340
-rw-r--r--objectivec/GPBCodedOutputStream.m1229
-rw-r--r--objectivec/GPBDescriptor.h143
-rw-r--r--objectivec/GPBDescriptor.m888
-rw-r--r--objectivec/GPBDescriptor_PackagePrivate.h293
-rw-r--r--objectivec/GPBDictionary.h2233
-rw-r--r--objectivec/GPBDictionary.m12627
-rw-r--r--objectivec/GPBDictionary_PackagePrivate.h577
-rw-r--r--objectivec/GPBExtensionField.h51
-rw-r--r--objectivec/GPBExtensionField.m525
-rw-r--r--objectivec/GPBExtensionField_PackagePrivate.h51
-rw-r--r--objectivec/GPBExtensionRegistry.h46
-rw-r--r--objectivec/GPBExtensionRegistry.m98
-rw-r--r--objectivec/GPBExtensionRegistry_PackagePrivate.h40
-rw-r--r--objectivec/GPBField.h56
-rw-r--r--objectivec/GPBField.m328
-rw-r--r--objectivec/GPBField_PackagePrivate.h49
-rw-r--r--objectivec/GPBMessage.h151
-rw-r--r--objectivec/GPBMessage.m4735
-rw-r--r--objectivec/GPBMessage_PackagePrivate.h124
-rw-r--r--objectivec/GPBProtocolBuffers.h45
-rw-r--r--objectivec/GPBProtocolBuffers.m49
-rw-r--r--objectivec/GPBProtocolBuffers_RuntimeSupport.h41
-rw-r--r--objectivec/GPBRootObject.h42
-rw-r--r--objectivec/GPBRootObject.m177
-rw-r--r--objectivec/GPBRootObject_PackagePrivate.h42
-rw-r--r--objectivec/GPBTypes.h102
-rw-r--r--objectivec/GPBUnknownFieldSet.h46
-rw-r--r--objectivec/GPBUnknownFieldSet.m422
-rw-r--r--objectivec/GPBUnknownFieldSet_PackagePrivate.h61
-rw-r--r--objectivec/GPBUtilities.h181
-rw-r--r--objectivec/GPBUtilities.m1645
-rw-r--r--objectivec/GPBUtilities_PackagePrivate.h426
-rw-r--r--objectivec/GPBWellKnownTypes.h48
-rw-r--r--objectivec/GPBWellKnownTypes.m117
-rw-r--r--objectivec/GPBWireFormat.h68
-rw-r--r--objectivec/GPBWireFormat.m78
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj919
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata7
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings8
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme125
-rw-r--r--objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme115
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj1093
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata7
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings8
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist62
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist21
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme134
-rw-r--r--objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme116
-rw-r--r--objectivec/Tests/Filter1.txt40
-rw-r--r--objectivec/Tests/Filter2.txt35
-rw-r--r--objectivec/Tests/GPBARCUnittestProtos.m57
-rw-r--r--objectivec/Tests/GPBArrayTests.m3365
-rw-r--r--objectivec/Tests/GPBCodedInputStreamTests.m290
-rw-r--r--objectivec/Tests/GPBCodedOuputStreamTests.m321
-rw-r--r--objectivec/Tests/GPBConcurrencyTests.m157
-rw-r--r--objectivec/Tests/GPBDescriptorTests.m232
-rw-r--r--objectivec/Tests/GPBDictionaryTests+Bool.m2421
-rw-r--r--objectivec/Tests/GPBDictionaryTests+Int32.m3650
-rw-r--r--objectivec/Tests/GPBDictionaryTests+Int64.m3650
-rw-r--r--objectivec/Tests/GPBDictionaryTests+String.m3362
-rw-r--r--objectivec/Tests/GPBDictionaryTests+UInt32.m3650
-rw-r--r--objectivec/Tests/GPBDictionaryTests+UInt64.m3649
-rw-r--r--objectivec/Tests/GPBDictionaryTests.pddm1044
-rw-r--r--objectivec/Tests/GPBFilteredMessageTests.m98
-rw-r--r--objectivec/Tests/GPBMessageTests+Merge.m700
-rw-r--r--objectivec/Tests/GPBMessageTests+Runtime.m1978
-rw-r--r--objectivec/Tests/GPBMessageTests+Serialization.m838
-rw-r--r--objectivec/Tests/GPBMessageTests.m1728
-rw-r--r--objectivec/Tests/GPBPerfTests.m306
-rw-r--r--objectivec/Tests/GPBStringTests.m516
-rw-r--r--objectivec/Tests/GPBSwiftTests.swift405
-rw-r--r--objectivec/Tests/GPBTestUtilities.h87
-rw-r--r--objectivec/Tests/GPBTestUtilities.m2350
-rw-r--r--objectivec/Tests/GPBUnittestProtos.m56
-rw-r--r--objectivec/Tests/GPBUnknownFieldSetTest.m255
-rw-r--r--objectivec/Tests/GPBUtilitiesTests.m363
-rw-r--r--objectivec/Tests/GPBWellKnownTypesTest.m102
-rw-r--r--objectivec/Tests/GPBWireFormatTests.m246
-rw-r--r--objectivec/Tests/UnitTests-Bridging-Header.h6
-rw-r--r--objectivec/Tests/UnitTests-Info.plist20
-rw-r--r--objectivec/Tests/golden_messagebin0 -> 493 bytes
-rw-r--r--objectivec/Tests/golden_packed_fields_messagebin0 -> 493 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/AppDelegate.m35
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json116
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.pngbin0 -> 8583 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.pngbin0 -> 17744 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.pngbin0 -> 8969 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.pngbin0 -> 18788 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.pngbin0 -> 7021 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.pngbin0 -> 13348 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.pngbin0 -> 11128 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.pngbin0 -> 21792 bytes
-rw-r--r--objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json49
-rw-r--r--objectivec/Tests/iOSTestHarness/Info.plist43
-rw-r--r--objectivec/Tests/iOSTestHarness/LaunchScreen.xib33
-rw-r--r--objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings2
-rw-r--r--objectivec/Tests/text_format_map_unittest_data.txt70
-rw-r--r--objectivec/Tests/text_format_unittest_data.txt116
-rw-r--r--objectivec/Tests/unittest_cycle.proto58
-rw-r--r--objectivec/Tests/unittest_filter.proto71
-rw-r--r--objectivec/Tests/unittest_name_mangling.proto37
-rw-r--r--objectivec/Tests/unittest_objc.proto389
-rw-r--r--objectivec/Tests/unittest_runtime_proto2.proto108
-rw-r--r--objectivec/Tests/unittest_runtime_proto3.proto101
-rw-r--r--objectivec/google/protobuf/Descriptor.pbobjc.h1046
-rw-r--r--objectivec/google/protobuf/Descriptor.pbobjc.m2205
-rw-r--r--objectivec/google/protobuf/Duration.pbobjc.h83
-rw-r--r--objectivec/google/protobuf/Duration.pbobjc.m85
-rw-r--r--objectivec/google/protobuf/Timestamp.pbobjc.h94
-rw-r--r--objectivec/google/protobuf/Timestamp.pbobjc.m85
-rw-r--r--protobuf-lite.pc.in4
-rw-r--r--protobuf.pc.in4
-rw-r--r--protoc-artifacts/Dockerfile40
-rw-r--r--protoc-artifacts/README.md29
-rwxr-xr-xprotoc-artifacts/build-protoc.sh5
-rw-r--r--python/MANIFEST.in14
-rwxr-xr-xpython/google/protobuf/internal/_parameterized.py2
-rw-r--r--python/google/protobuf/internal/descriptor_database_test.py2
-rw-r--r--python/google/protobuf/internal/descriptor_pool_test.py2
-rwxr-xr-xpython/google/protobuf/internal/descriptor_test.py2
-rwxr-xr-xpython/google/protobuf/internal/generator_test.py2
-rw-r--r--python/google/protobuf/internal/message_factory_test.py2
-rwxr-xr-xpython/google/protobuf/internal/message_test.py2
-rw-r--r--python/google/protobuf/internal/proto_builder_test.py2
-rwxr-xr-xpython/google/protobuf/internal/reflection_test.py2
-rwxr-xr-xpython/google/protobuf/internal/service_reflection_test.py4
-rw-r--r--python/google/protobuf/internal/symbol_database_test.py2
-rwxr-xr-xpython/google/protobuf/internal/text_encoding_test.py2
-rwxr-xr-xpython/google/protobuf/internal/text_format_test.py2
-rwxr-xr-xpython/google/protobuf/internal/unknown_fields_test.py2
-rwxr-xr-xpython/google/protobuf/internal/wire_format_test.py2
-rwxr-xr-xpython/setup.py169
-rw-r--r--ruby/.gitignore2
-rw-r--r--ruby/Gemfile.lock2
-rw-r--r--ruby/README.md7
-rw-r--r--ruby/Rakefile3
-rw-r--r--ruby/ext/google/protobuf_c/repeated_field.c20
-rw-r--r--ruby/ext/google/protobuf_c/storage.c4
-rw-r--r--ruby/google-protobuf.gemspec3
-rw-r--r--ruby/lib/google/protobuf.rb2
-rw-r--r--ruby/lib/google/protobuf/repeated_field.rb40
-rw-r--r--ruby/pom.xml2
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java29
-rw-r--r--ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java24
-rw-r--r--ruby/tests/basic.rb57
-rw-r--r--src/Makefile.am37
-rw-r--r--src/google/protobuf/any.proto14
-rw-r--r--src/google/protobuf/api.proto105
-rwxr-xr-xsrc/google/protobuf/arena.cc7
-rw-r--r--src/google/protobuf/arena.h5
-rw-r--r--src/google/protobuf/arena_nc_test.py2
-rw-r--r--src/google/protobuf/compiler/command_line_interface_unittest.cc6
-rw-r--r--src/google/protobuf/compiler/cpp/cpp_unittest.cc9
-rw-r--r--src/google/protobuf/compiler/java/java_extension.cc8
-rw-r--r--src/google/protobuf/compiler/java/java_extension.h12
-rw-r--r--src/google/protobuf/compiler/java/java_file.cc92
-rw-r--r--src/google/protobuf/compiler/java/java_message.cc18
-rw-r--r--src/google/protobuf/compiler/java/java_message.h12
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum.cc40
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.cc32
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_enum_field.h1
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_extension.cc2
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_field.h1
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_generator.cc6
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.cc91
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message.h2
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.cc29
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_message_field.h3
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_params.h20
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.cc8
-rw-r--r--src/google/protobuf/compiler/javanano/javanano_primitive_field.h1
-rw-r--r--src/google/protobuf/compiler/main.cc6
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum.cc199
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum.h73
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc129
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_enum_field.h77
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_extension.cc166
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_extension.h73
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.cc474
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_field.h166
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.cc392
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_file.h94
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_generator.cc95
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_generator.h60
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.cc1131
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers.h176
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc242
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.cc161
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_map_field.h64
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message.cc642
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message.h103
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message_field.cc90
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_message_field.h71
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_oneof.cc139
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_oneof.h77
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc162
-rw-r--r--src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h82
-rw-r--r--src/google/protobuf/descriptor.h4
-rw-r--r--src/google/protobuf/descriptor.pb.cc6
-rw-r--r--src/google/protobuf/descriptor.proto1
-rw-r--r--src/google/protobuf/duration.proto10
-rw-r--r--src/google/protobuf/empty.proto50
-rw-r--r--src/google/protobuf/field_mask.proto2
-rw-r--r--src/google/protobuf/preserve_unknown_enum_test.cc4
-rw-r--r--src/google/protobuf/repeated_field.h2
-rw-r--r--src/google/protobuf/source_context.proto46
-rw-r--r--src/google/protobuf/struct.proto19
-rw-r--r--src/google/protobuf/stubs/atomicops_internals_pnacl.h176
-rw-r--r--src/google/protobuf/stubs/common.h42
-rwxr-xr-xsrc/google/protobuf/stubs/hash.h11
-rw-r--r--src/google/protobuf/stubs/platform_macros.h6
-rw-r--r--src/google/protobuf/stubs/type_traits.h4
-rw-r--r--src/google/protobuf/testing/googletest.cc4
-rw-r--r--src/google/protobuf/timestamp.proto15
-rw-r--r--src/google/protobuf/type.proto197
-rw-r--r--src/google/protobuf/unittest_drop_unknown_fields.proto1
-rw-r--r--src/google/protobuf/unittest_preserve_unknown_enum.proto1
-rw-r--r--src/google/protobuf/wrappers.proto2
254 files changed, 84480 insertions, 321 deletions
diff --git a/.gitignore b/.gitignore
index c21c20cf..6508eccb 100644
--- a/.gitignore
+++ b/.gitignore
@@ -51,6 +51,7 @@ cpp_test*.pb.*
*.pyc
*.egg-info
*_pb2.py
+python/*.egg
python/.eggs/
python/build/
python/google/protobuf/compiler/
@@ -82,3 +83,9 @@ vsprojects/Release
# NuGet packages: we want the repository configuration, but not the
# packages themselves.
/csharp/src/packages/*/
+
+# Directories created by opening the Objective C Xcode projects.
+objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcuserdata/
+objectivec/ProtocolBuffers_OSX.xcodeproj/xcuserdata/
+objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcuserdata/
+objectivec/ProtocolBuffers_iOS.xcodeproj/xcuserdata/
diff --git a/.travis.yml b/.travis.yml
index cbddac58..354be896 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -14,6 +14,7 @@ script:
- cd python && python setup.py build && python setup.py test && cd ..
- export LD_LIBRARY_PATH=../src/.libs
- cd python && python setup.py build --cpp_implementation && python setup.py test --cpp_implementation && cd ..
+ - cd conformance && make test_java && cd ..
- make distcheck -j2
notifications:
email: false
diff --git a/Makefile.am b/Makefile.am
index 4fd93f26..eecffa1f 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -197,6 +197,128 @@ javanano_EXTRA_DIST=
javanano/README.md \
javanano/pom.xml
+objectivec_EXTRA_DIST= \
+ objectivec/DevTools/generate_descriptors_proto.sh \
+ objectivec/DevTools/pddm.py \
+ objectivec/DevTools/pddm_tests.py \
+ objectivec/google/protobuf/Descriptor.pbobjc.h \
+ objectivec/google/protobuf/Descriptor.pbobjc.m \
+ objectivec/google/protobuf/Duration.pbobjc.h \
+ objectivec/google/protobuf/Duration.pbobjc.m \
+ objectivec/google/protobuf/Timestamp.pbobjc.h \
+ objectivec/google/protobuf/Timestamp.pbobjc.m \
+ objectivec/GPBArray.h \
+ objectivec/GPBArray.m \
+ objectivec/GPBArray_PackagePrivate.h \
+ objectivec/GPBBootstrap.h \
+ objectivec/GPBCodedInputStream.h \
+ objectivec/GPBCodedInputStream.m \
+ objectivec/GPBCodedInputStream_PackagePrivate.h \
+ objectivec/GPBCodedOutputStream.h \
+ objectivec/GPBCodedOutputStream.m \
+ objectivec/GPBDescriptor.h \
+ objectivec/GPBDescriptor.m \
+ objectivec/GPBDescriptor_PackagePrivate.h \
+ objectivec/GPBDictionary.h \
+ objectivec/GPBDictionary.m \
+ objectivec/GPBDictionary_PackagePrivate.h \
+ objectivec/GPBExtensionField.h \
+ objectivec/GPBExtensionField.m \
+ objectivec/GPBExtensionField_PackagePrivate.h \
+ objectivec/GPBExtensionRegistry.h \
+ objectivec/GPBExtensionRegistry.m \
+ objectivec/GPBExtensionRegistry_PackagePrivate.h \
+ objectivec/GPBField.h \
+ objectivec/GPBField.m \
+ objectivec/GPBField_PackagePrivate.h \
+ objectivec/GPBMessage.h \
+ objectivec/GPBMessage.m \
+ objectivec/GPBMessage_PackagePrivate.h \
+ objectivec/GPBProtocolBuffers.h \
+ objectivec/GPBProtocolBuffers.m \
+ objectivec/GPBProtocolBuffers_RuntimeSupport.h \
+ objectivec/GPBRootObject.h \
+ objectivec/GPBRootObject.m \
+ objectivec/GPBRootObject_PackagePrivate.h \
+ objectivec/GPBTypes.h \
+ objectivec/GPBUnknownFieldSet.h \
+ objectivec/GPBUnknownFieldSet.m \
+ objectivec/GPBUnknownFieldSet_PackagePrivate.h \
+ objectivec/GPBUtilities.h \
+ objectivec/GPBUtilities.m \
+ objectivec/GPBUtilities_PackagePrivate.h \
+ objectivec/GPBWellKnownTypes.h \
+ objectivec/GPBWellKnownTypes.m \
+ objectivec/GPBWireFormat.h \
+ objectivec/GPBWireFormat.m \
+ objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj \
+ objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
+ objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \
+ objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist \
+ objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist \
+ objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
+ objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
+ objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj \
+ objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
+ objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \
+ objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
+ objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
+ objectivec/Tests/Filter1.txt \
+ objectivec/Tests/Filter2.txt \
+ objectivec/Tests/golden_message \
+ objectivec/Tests/golden_packed_fields_message \
+ objectivec/Tests/GPBARCUnittestProtos.m \
+ objectivec/Tests/GPBArrayTests.m \
+ objectivec/Tests/GPBCodedInputStreamTests.m \
+ objectivec/Tests/GPBCodedOuputStreamTests.m \
+ objectivec/Tests/GPBConcurrencyTests.m \
+ objectivec/Tests/GPBDescriptorTests.m \
+ objectivec/Tests/GPBDictionaryTests+Bool.m \
+ objectivec/Tests/GPBDictionaryTests+Int32.m \
+ objectivec/Tests/GPBDictionaryTests+Int64.m \
+ objectivec/Tests/GPBDictionaryTests+String.m \
+ objectivec/Tests/GPBDictionaryTests+UInt32.m \
+ objectivec/Tests/GPBDictionaryTests+UInt64.m \
+ objectivec/Tests/GPBDictionaryTests.pddm \
+ objectivec/Tests/GPBFilteredMessageTests.m \
+ objectivec/Tests/GPBMessageTests+Merge.m \
+ objectivec/Tests/GPBMessageTests+Runtime.m \
+ objectivec/Tests/GPBMessageTests+Serialization.m \
+ objectivec/Tests/GPBMessageTests.m \
+ objectivec/Tests/GPBPerfTests.m \
+ objectivec/Tests/GPBStringTests.m \
+ objectivec/Tests/GPBSwiftTests.swift \
+ objectivec/Tests/GPBTestUtilities.h \
+ objectivec/Tests/GPBTestUtilities.m \
+ objectivec/Tests/GPBUnittestProtos.m \
+ objectivec/Tests/GPBUnknownFieldSetTest.m \
+ objectivec/Tests/GPBUtilitiesTests.m \
+ objectivec/Tests/GPBWellKnownTypesTest.m \
+ objectivec/Tests/GPBWireFormatTests.m \
+ objectivec/Tests/iOSTestHarness/AppDelegate.m \
+ objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings \
+ objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json \
+ objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png \
+ objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png \
+ objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png \
+ objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png \
+ objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png \
+ objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png \
+ objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png \
+ objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png \
+ objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json \
+ objectivec/Tests/iOSTestHarness/Info.plist \
+ objectivec/Tests/iOSTestHarness/LaunchScreen.xib \
+ objectivec/Tests/text_format_map_unittest_data.txt \
+ objectivec/Tests/text_format_unittest_data.txt \
+ objectivec/Tests/unittest_cycle.proto \
+ objectivec/Tests/unittest_filter.proto \
+ objectivec/Tests/unittest_name_mangling.proto \
+ objectivec/Tests/unittest_objc.proto \
+ objectivec/Tests/unittest_runtime_proto2.proto \
+ objectivec/Tests/unittest_runtime_proto3.proto \
+ objectivec/Tests/UnitTests-Bridging-Header.h \
+ objectivec/Tests/UnitTests-Info.plist
python_EXTRA_DIST= \
python/google/protobuf/internal/api_implementation.cc \
@@ -301,7 +423,7 @@ ruby_EXTRA_DIST= \
ruby/tests/generated_code.rb \
ruby/tests/generated_code_test.rb
-all_EXTRA_DIST=$(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
+all_EXTRA_DIST=$(java_EXTRA_DIST) $(javanano_EXTRA_DIST) $(objectivec_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST) \
autogen.sh \
diff --git a/conformance/ConformanceJava.java b/conformance/ConformanceJava.java
new file mode 100644
index 00000000..c1a53141
--- /dev/null
+++ b/conformance/ConformanceJava.java
@@ -0,0 +1,120 @@
+
+import com.google.protobuf.conformance.Conformance;
+import com.google.protobuf.InvalidProtocolBufferException;
+
+class ConformanceJava {
+ private int testCount = 0;
+
+ private boolean readFromStdin(byte[] buf, int len) throws Exception {
+ int ofs = 0;
+ while (len > 0) {
+ int read = System.in.read(buf, ofs, len);
+ if (read == -1) {
+ return false; // EOF
+ }
+ ofs += read;
+ len -= read;
+ }
+
+ return true;
+ }
+
+ private void writeToStdout(byte[] buf) throws Exception {
+ System.out.write(buf);
+ }
+
+ // Returns -1 on EOF (the actual values will always be positive).
+ private int readLittleEndianIntFromStdin() throws Exception {
+ byte[] buf = new byte[4];
+ if (!readFromStdin(buf, 4)) {
+ return -1;
+ }
+ return buf[0] | (buf[1] << 1) | (buf[2] << 2) | (buf[3] << 3);
+ }
+
+ private void writeLittleEndianIntToStdout(int val) throws Exception {
+ byte[] buf = new byte[4];
+ buf[0] = (byte)val;
+ buf[1] = (byte)(val >> 8);
+ buf[2] = (byte)(val >> 16);
+ buf[3] = (byte)(val >> 24);
+ writeToStdout(buf);
+ }
+
+ private Conformance.ConformanceResponse doTest(Conformance.ConformanceRequest request) {
+ Conformance.TestAllTypes testMessage;
+
+ switch (request.getPayloadCase()) {
+ case PROTOBUF_PAYLOAD: {
+ try {
+ testMessage = Conformance.TestAllTypes.parseFrom(request.getProtobufPayload());
+ } catch (InvalidProtocolBufferException e) {
+ return Conformance.ConformanceResponse.newBuilder().setParseError(e.getMessage()).build();
+ }
+ break;
+ }
+ case JSON_PAYLOAD: {
+ return Conformance.ConformanceResponse.newBuilder().setRuntimeError("JSON not yet supported.").build();
+ }
+ case PAYLOAD_NOT_SET: {
+ throw new RuntimeException("Request didn't have payload.");
+ }
+
+ default: {
+ throw new RuntimeException("Unexpected payload case.");
+ }
+ }
+
+ switch (request.getRequestedOutput()) {
+ case UNSPECIFIED:
+ throw new RuntimeException("Unspecified output format.");
+
+ case PROTOBUF:
+ return Conformance.ConformanceResponse.newBuilder().setProtobufPayload(testMessage.toByteString()).build();
+
+ case JSON:
+ return Conformance.ConformanceResponse.newBuilder().setRuntimeError("JSON not yet supported.").build();
+
+ default: {
+ throw new RuntimeException("Unexpected request output.");
+ }
+ }
+ }
+
+ private boolean doTestIo() throws Exception {
+ int bytes = readLittleEndianIntFromStdin();
+
+ if (bytes == -1) {
+ return false; // EOF
+ }
+
+ byte[] serializedInput = new byte[bytes];
+
+ if (!readFromStdin(serializedInput, bytes)) {
+ throw new RuntimeException("Unexpected EOF from test program.");
+ }
+
+ Conformance.ConformanceRequest request =
+ Conformance.ConformanceRequest.parseFrom(serializedInput);
+ Conformance.ConformanceResponse response = doTest(request);
+ byte[] serializedOutput = response.toByteArray();
+
+ writeLittleEndianIntToStdout(serializedOutput.length);
+ writeToStdout(serializedOutput);
+
+ return true;
+ }
+
+ public void run() throws Exception {
+ while (doTestIo()) {
+ // Empty.
+ }
+
+ System.err.println("ConformanceJava: received EOF from test runner after " +
+ this.testCount + " tests");
+ }
+
+ public static void main(String[] args) throws Exception {
+ new ConformanceJava().run();
+ }
+}
diff --git a/conformance/Makefile.am b/conformance/Makefile.am
index 0c4eae75..95343f14 100644
--- a/conformance/Makefile.am
+++ b/conformance/Makefile.am
@@ -21,30 +21,43 @@ conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src
if USE_EXTERNAL_PROTOC
-unittest_proto_middleman: $(protoc_inputs)
- $(PROTOC) -I$(srcdir) --cpp_out=. $^
- touch unittest_proto_middleman
+protoc_middleman: $(protoc_inputs)
+ $(PROTOC) -I$(srcdir) --cpp_out=. --java_out=. $^
+ touch protoc_middleman
else
# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
# relative to srcdir, which may not be the same as the current directory when
# building out-of-tree.
-unittest_proto_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(protoc_inputs)
- oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd $(protoc_inputs) )
- touch unittest_proto_middleman
+protoc_middleman: $(top_srcdir)/src/protoc$(EXEEXT) $(protoc_inputs)
+ oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd --java_out=$$oldpwd $(protoc_inputs) )
+ touch protoc_middleman
endif
-$(protoc_outputs): unittest_proto_middleman
+$(protoc_outputs): protoc_middleman
BUILT_SOURCES = $(protoc_outputs)
-CLEANFILES = $(protoc_outputs) unittest_proto_middleman
+CLEANFILES = $(protoc_outputs) protoc_middleman javac_middleman conformance-java
MAINTAINERCLEANFILES = \
Makefile.in
+javac_middleman: ConformanceJava.java protoc_middleman
+ javac -classpath ../java/target/classes ConformanceJava.java com/google/protobuf/conformance/Conformance.java
+ @touch javac_middleman
+
+conformance-java: javac_middleman
+ @echo "Writing shortcut script conformance-java..."
+ @echo '#! /bin/sh' > conformance-java
+ @echo 'java -classpath .:../java/target/classes ConformanceJava "$$@"' >> conformance-java
+ @chmod +x conformance-java
+
# Targets for actually running tests.
-test_cpp: unittest_proto_middleman conformance-test-runner conformance-cpp
+test_cpp: protoc_middleman conformance-test-runner conformance-cpp
./conformance-test-runner ./conformance-cpp
+
+test_java: protoc_middleman conformance-test-runner conformance-java
+ ./conformance-test-runner ./conformance-java
diff --git a/conformance/conformance.proto b/conformance/conformance.proto
index 0fb66cf9..7b676898 100644
--- a/conformance/conformance.proto
+++ b/conformance/conformance.proto
@@ -30,6 +30,7 @@
syntax = "proto3";
package conformance;
+option java_package = "com.google.protobuf.conformance";
// This defines the conformance testing protocol. This protocol exists between
// the conformance test suite itself and the code being tested. For each test,
diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc
index 21277700..ca5877bd 100644
--- a/conformance/conformance_test_runner.cc
+++ b/conformance/conformance_test_runner.cc
@@ -48,9 +48,9 @@
// Every test consists of a ConformanceRequest/ConformanceResponse
// request/reply pair. The protocol on the pipe is simply:
//
-// 1. tester sends 4-byte length N
+// 1. tester sends 4-byte length N (little endian)
// 2. tester sends N bytes representing a ConformanceRequest proto
-// 3. testee sends 4-byte length M
+// 3. testee sends 4-byte length M (little endian)
// 4. testee sends M bytes representing a ConformanceResponse proto
#include <errno.h>
diff --git a/examples/add_person.py b/examples/add_person.py
index 78e56966..5a7b968e 100755
--- a/examples/add_person.py
+++ b/examples/add_person.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
# See README.txt for information and build instructions.
diff --git a/examples/list_people.py b/examples/list_people.py
index f9f36b96..d470349a 100755
--- a/examples/list_people.py
+++ b/examples/list_people.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
# See README.txt for information and build instructions.
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index b25a3c6a..2dad36ab 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -27,6 +27,7 @@ __EOF__
fi
cd src
+make $@ google/protobuf/stubs/pbconfig.h
CORE_PROTO_IS_CORRECT=0
while [ $CORE_PROTO_IS_CORRECT -ne 1 ]
do
diff --git a/javanano/README.md b/javanano/README.md
index 7d696aa7..e19b90b1 100644
--- a/javanano/README.md
+++ b/javanano/README.md
@@ -145,6 +145,7 @@ optional_field_style -> default or accessors
enum_style -> c or java
ignore_services -> true or false
parcelable_messages -> true or false
+generate_intdefs -> true or false
```
**java_package=\<file-name\>|\<package-name\>** (no default)
@@ -302,6 +303,28 @@ parcelable_messages -> true or false
Android-specific option to generate Parcelable messages.
+**generate_intdefs={true,false}** (default: false)
+ Android-specific option to generate @IntDef annotations for enums.
+
+ If turned on, an '@IntDef' annotation (a public @interface) will be
+ generated for each enum, and every integer parameter and return
+ value in the generated code meant for this enum will be annotated
+ with it. This interface is generated with the same name and at the
+ same place as the enum members' container interfaces described
+ above under 'enum_style=java', regardless of the enum_style option
+ used. When this is combined with enum_style=java, the interface
+ will be both the '@IntDef' annotation and the container of the enum
+ members; otherwise the interface has an empty body.
+
+ Your app must declare a compile-time dependency on the
+ android-support-annotations library.
+
+ For more information on how these @IntDef annotations help with
+ compile-time type safety, see:
+ https://sites.google.com/a/android.com/tools/tech-docs/support-annotations
+ and
+ https://developer.android.com/reference/android/support/annotation/IntDef.html
+
To use nano protobufs within the Android repo:
----------------------------------------------
diff --git a/javanano/pom.xml b/javanano/pom.xml
index 7a2be9df..3d8cfb9f 100644
--- a/javanano/pom.xml
+++ b/javanano/pom.xml
@@ -97,19 +97,19 @@
<arg value="src/test/java/com/google/protobuf/nano/map_test.proto" />
</exec>
<exec executable="../src/protoc">
- <arg value="--javanano_out=store_unknown_fields=true,generate_equals=true:target/generated-test-sources" />
+ <arg value="--javanano_out=store_unknown_fields=true,generate_equals=true,generate_clone=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_singular_nano.proto" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_repeated_nano.proto" />
</exec>
<exec executable="../src/protoc">
- <arg value="--javanano_out=store_unknown_fields=true:target/generated-test-sources" />
+ <arg value="--javanano_out=store_unknown_fields=true,generate_clone=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_extension_packed_nano.proto" />
</exec>
<exec executable="../src/protoc">
- <arg value="--javanano_out=java_nano_generate_has=true,generate_equals=true:target/generated-test-sources" />
+ <arg value="--javanano_out=java_nano_generate_has=true,generate_equals=true,generate_clone=true:target/generated-test-sources" />
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_has_nano.proto" />
</exec>
@@ -139,6 +139,15 @@
<arg value="--proto_path=src/test/java/com" />
<arg value="src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto" />
</exec>
+ <exec executable="../src/protoc">
+ <arg value="--javanano_out=
+ optional_field_style=reftypes_compat_mode,
+ generate_equals=true,
+ java_outer_classname=google/protobuf/nano/unittest_reference_types_nano.proto|NanoReferenceTypesCompat
+ :target/generated-test-sources" />
+ <arg value="--proto_path=src/test/java/com" />
+ <arg value="src/test/java/com/google/protobuf/nano/unittest_reference_types_nano.proto" />
+ </exec>
</tasks>
<testSourceRoot>target/generated-test-sources</testSourceRoot>
</configuration>
diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
index 4b45c6d2..f3993155 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/CodedInputByteBufferNano.java
@@ -236,6 +236,8 @@ public final class CodedInputByteBufferNano {
System.arraycopy(buffer, bufferPos, result, 0, size);
bufferPos += size;
return result;
+ } else if (size == 0) {
+ return WireFormatNano.EMPTY_BYTES;
} else {
// Slow path: Build a byte array first then copy it.
return readRawBytes(size);
diff --git a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
index 35907183..b1b0c53a 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/CodedOutputByteBufferNano.java
@@ -31,6 +31,9 @@
package com.google.protobuf.nano;
import java.io.IOException;
+import java.nio.BufferOverflowException;
+import java.nio.ByteBuffer;
+import java.nio.ReadOnlyBufferException;
/**
* Encodes and writes protocol message fields.
@@ -47,15 +50,17 @@ import java.io.IOException;
* @author kneton@google.com Kenton Varda
*/
public final class CodedOutputByteBufferNano {
- private final byte[] buffer;
- private final int limit;
- private int position;
+ /* max bytes per java UTF-16 char in UTF-8 */
+ private static final int MAX_UTF8_EXPANSION = 3;
+ private final ByteBuffer buffer;
private CodedOutputByteBufferNano(final byte[] buffer, final int offset,
final int length) {
+ this(ByteBuffer.wrap(buffer, offset, length));
+ }
+
+ private CodedOutputByteBufferNano(final ByteBuffer buffer) {
this.buffer = buffer;
- position = offset;
- limit = offset + length;
}
/**
@@ -287,14 +292,213 @@ public final class CodedOutputByteBufferNano {
/** Write a {@code string} field to the stream. */
public void writeStringNoTag(final String value) throws IOException {
- // Unfortunately there does not appear to be any way to tell Java to encode
- // UTF-8 directly into our buffer, so we have to let it create its own byte
- // array and then copy.
- final byte[] bytes = value.getBytes(InternalNano.UTF_8);
- writeRawVarint32(bytes.length);
- writeRawBytes(bytes);
+ // UTF-8 byte length of the string is at least its UTF-16 code unit length (value.length()),
+ // and at most 3 times of it. Optimize for the case where we know this length results in a
+ // constant varint length - saves measuring length of the string.
+ try {
+ final int minLengthVarIntSize = computeRawVarint32Size(value.length());
+ final int maxLengthVarIntSize = computeRawVarint32Size(value.length() * MAX_UTF8_EXPANSION);
+ if (minLengthVarIntSize == maxLengthVarIntSize) {
+ int oldPosition = buffer.position();
+ // Buffer.position, when passed a position that is past its limit, throws
+ // IllegalArgumentException, and this class is documented to throw
+ // OutOfSpaceException instead.
+ if (buffer.remaining() < minLengthVarIntSize) {
+ throw new OutOfSpaceException(oldPosition + minLengthVarIntSize, buffer.limit());
+ }
+ buffer.position(oldPosition + minLengthVarIntSize);
+ encode(value, buffer);
+ int newPosition = buffer.position();
+ buffer.position(oldPosition);
+ writeRawVarint32(newPosition - oldPosition - minLengthVarIntSize);
+ buffer.position(newPosition);
+ } else {
+ writeRawVarint32(encodedLength(value));
+ encode(value, buffer);
+ }
+ } catch (BufferOverflowException e) {
+ final OutOfSpaceException outOfSpaceException = new OutOfSpaceException(buffer.position(),
+ buffer.limit());
+ outOfSpaceException.initCause(e);
+ throw outOfSpaceException;
+ }
+ }
+
+ // These UTF-8 handling methods are copied from Guava's Utf8 class.
+ /**
+ * Returns the number of bytes in the UTF-8-encoded form of {@code sequence}. For a string,
+ * this method is equivalent to {@code string.getBytes(UTF_8).length}, but is more efficient in
+ * both time and space.
+ *
+ * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
+ * surrogates)
+ */
+ private static int encodedLength(CharSequence sequence) {
+ // Warning to maintainers: this implementation is highly optimized.
+ int utf16Length = sequence.length();
+ int utf8Length = utf16Length;
+ int i = 0;
+
+ // This loop optimizes for pure ASCII.
+ while (i < utf16Length && sequence.charAt(i) < 0x80) {
+ i++;
+ }
+
+ // This loop optimizes for chars less than 0x800.
+ for (; i < utf16Length; i++) {
+ char c = sequence.charAt(i);
+ if (c < 0x800) {
+ utf8Length += ((0x7f - c) >>> 31); // branch free!
+ } else {
+ utf8Length += encodedLengthGeneral(sequence, i);
+ break;
+ }
+ }
+
+ if (utf8Length < utf16Length) {
+ // Necessary and sufficient condition for overflow because of maximum 3x expansion
+ throw new IllegalArgumentException("UTF-8 length does not fit in int: "
+ + (utf8Length + (1L << 32)));
+ }
+ return utf8Length;
+ }
+
+ private static int encodedLengthGeneral(CharSequence sequence, int start) {
+ int utf16Length = sequence.length();
+ int utf8Length = 0;
+ for (int i = start; i < utf16Length; i++) {
+ char c = sequence.charAt(i);
+ if (c < 0x800) {
+ utf8Length += (0x7f - c) >>> 31; // branch free!
+ } else {
+ utf8Length += 2;
+ // jdk7+: if (Character.isSurrogate(c)) {
+ if (Character.MIN_SURROGATE <= c && c <= Character.MAX_SURROGATE) {
+ // Check that we have a well-formed surrogate pair.
+ int cp = Character.codePointAt(sequence, i);
+ if (cp < Character.MIN_SUPPLEMENTARY_CODE_POINT) {
+ throw new IllegalArgumentException("Unpaired surrogate at index " + i);
+ }
+ i++;
+ }
+ }
+ }
+ return utf8Length;
}
+ /**
+ * Encodes {@code sequence} into UTF-8, in {@code byteBuffer}. For a string, this method is
+ * equivalent to {@code buffer.put(string.getBytes(UTF_8))}, but is more efficient in both time
+ * and space. Bytes are written starting at the current position. This method requires paired
+ * surrogates, and therefore does not support chunking.
+ *
+ * <p>To ensure sufficient space in the output buffer, either call {@link #encodedLength} to
+ * compute the exact amount needed, or leave room for {@code 3 * sequence.length()}, which is the
+ * largest possible number of bytes that any input can be encoded to.
+ *
+ * @throws IllegalArgumentException if {@code sequence} contains ill-formed UTF-16 (unpaired
+ * surrogates)
+ * @throws BufferOverflowException if {@code sequence} encoded in UTF-8 does not fit in
+ * {@code byteBuffer}'s remaining space.
+ * @throws ReadOnlyBufferException if {@code byteBuffer} is a read-only buffer.
+ */
+ private static void encode(CharSequence sequence, ByteBuffer byteBuffer) {
+ if (byteBuffer.isReadOnly()) {
+ throw new ReadOnlyBufferException();
+ } else if (byteBuffer.hasArray()) {
+ try {
+ int encoded = encode(sequence,
+ byteBuffer.array(),
+ byteBuffer.arrayOffset() + byteBuffer.position(),
+ byteBuffer.remaining());
+ byteBuffer.position(encoded - byteBuffer.arrayOffset());
+ } catch (ArrayIndexOutOfBoundsException e) {
+ BufferOverflowException boe = new BufferOverflowException();
+ boe.initCause(e);
+ throw boe;
+ }
+ } else {
+ encodeDirect(sequence, byteBuffer);
+ }
+ }
+
+ private static void encodeDirect(CharSequence sequence, ByteBuffer byteBuffer) {
+ int utf16Length = sequence.length();
+ for (int i = 0; i < utf16Length; i++) {
+ final char c = sequence.charAt(i);
+ if (c < 0x80) { // ASCII
+ byteBuffer.put((byte) c);
+ } else if (c < 0x800) { // 11 bits, two UTF-8 bytes
+ byteBuffer.put((byte) ((0xF << 6) | (c >>> 6)));
+ byteBuffer.put((byte) (0x80 | (0x3F & c)));
+ } else if (c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) {
+ // Maximium single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ byteBuffer.put((byte) ((0xF << 5) | (c >>> 12)));
+ byteBuffer.put((byte) (0x80 | (0x3F & (c >>> 6))));
+ byteBuffer.put((byte) (0x80 | (0x3F & c)));
+ } else {
+ final char low;
+ if (i + 1 == sequence.length()
+ || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
+ throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1));
+ }
+ int codePoint = Character.toCodePoint(c, low);
+ byteBuffer.put((byte) ((0xF << 4) | (codePoint >>> 18)));
+ byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 12))));
+ byteBuffer.put((byte) (0x80 | (0x3F & (codePoint >>> 6))));
+ byteBuffer.put((byte) (0x80 | (0x3F & codePoint)));
+ }
+ }
+ }
+
+ private static int encode(CharSequence sequence, byte[] bytes, int offset, int length) {
+ int utf16Length = sequence.length();
+ int j = offset;
+ int i = 0;
+ int limit = offset + length;
+ // Designed to take advantage of
+ // https://wikis.oracle.com/display/HotSpotInternals/RangeCheckElimination
+ for (char c; i < utf16Length && i + j < limit && (c = sequence.charAt(i)) < 0x80; i++) {
+ bytes[j + i] = (byte) c;
+ }
+ if (i == utf16Length) {
+ return j + utf16Length;
+ }
+ j += i;
+ for (char c; i < utf16Length; i++) {
+ c = sequence.charAt(i);
+ if (c < 0x80 && j < limit) {
+ bytes[j++] = (byte) c;
+ } else if (c < 0x800 && j <= limit - 2) { // 11 bits, two UTF-8 bytes
+ bytes[j++] = (byte) ((0xF << 6) | (c >>> 6));
+ bytes[j++] = (byte) (0x80 | (0x3F & c));
+ } else if ((c < Character.MIN_SURROGATE || Character.MAX_SURROGATE < c) && j <= limit - 3) {
+ // Maximum single-char code point is 0xFFFF, 16 bits, three UTF-8 bytes
+ bytes[j++] = (byte) ((0xF << 5) | (c >>> 12));
+ bytes[j++] = (byte) (0x80 | (0x3F & (c >>> 6)));
+ bytes[j++] = (byte) (0x80 | (0x3F & c));
+ } else if (j <= limit - 4) {
+ // Minimum code point represented by a surrogate pair is 0x10000, 17 bits, four UTF-8 bytes
+ final char low;
+ if (i + 1 == sequence.length()
+ || !Character.isSurrogatePair(c, (low = sequence.charAt(++i)))) {
+ throw new IllegalArgumentException("Unpaired surrogate at index " + (i - 1));
+ }
+ int codePoint = Character.toCodePoint(c, low);
+ bytes[j++] = (byte) ((0xF << 4) | (codePoint >>> 18));
+ bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 12)));
+ bytes[j++] = (byte) (0x80 | (0x3F & (codePoint >>> 6)));
+ bytes[j++] = (byte) (0x80 | (0x3F & codePoint));
+ } else {
+ throw new ArrayIndexOutOfBoundsException("Failed writing " + c + " at index " + j);
+ }
+ }
+ return j;
+ }
+
+ // End guava UTF-8 methods
+
+
/** Write a {@code group} field to the stream. */
public void writeGroupNoTag(final MessageNano value) throws IOException {
value.writeTo(this);
@@ -602,9 +806,8 @@ public final class CodedOutputByteBufferNano {
* {@code string} field.
*/
public static int computeStringSizeNoTag(final String value) {
- final byte[] bytes = value.getBytes(InternalNano.UTF_8);
- return computeRawVarint32Size(bytes.length) +
- bytes.length;
+ final int length = encodedLength(value);
+ return computeRawVarint32Size(length) + length;
}
/**
@@ -687,7 +890,7 @@ public final class CodedOutputByteBufferNano {
* Otherwise, throws {@code UnsupportedOperationException}.
*/
public int spaceLeft() {
- return limit - position;
+ return buffer.remaining();
}
/**
@@ -705,6 +908,23 @@ public final class CodedOutputByteBufferNano {
}
/**
+ * Returns the position within the internal buffer.
+ */
+ public int position() {
+ return buffer.position();
+ }
+
+ /**
+ * Resets the position within the internal buffer to zero.
+ *
+ * @see #position
+ * @see #spaceLeft
+ */
+ public void reset() {
+ buffer.clear();
+ }
+
+ /**
* If you create a CodedOutputStream around a simple flat array, you must
* not attempt to write more bytes than the array has space. Otherwise,
* this exception will be thrown.
@@ -720,12 +940,12 @@ public final class CodedOutputByteBufferNano {
/** Write a single byte. */
public void writeRawByte(final byte value) throws IOException {
- if (position == limit) {
+ if (!buffer.hasRemaining()) {
// We're writing to a single buffer.
- throw new OutOfSpaceException(position, limit);
+ throw new OutOfSpaceException(buffer.position(), buffer.limit());
}
- buffer[position++] = value;
+ buffer.put(value);
}
/** Write a single byte, represented by an integer value. */
@@ -741,13 +961,11 @@ public final class CodedOutputByteBufferNano {
/** Write part of an array of bytes. */
public void writeRawBytes(final byte[] value, int offset, int length)
throws IOException {
- if (limit - position >= length) {
- // We have room in the current buffer.
- System.arraycopy(value, offset, buffer, position, length);
- position += length;
+ if (buffer.remaining() >= length) {
+ buffer.put(value, offset, length);
} else {
// We're writing to a single buffer.
- throw new OutOfSpaceException(position, limit);
+ throw new OutOfSpaceException(buffer.position(), buffer.limit());
}
}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java b/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
index b979390d..87973d76 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/ExtendableMessageNano.java
@@ -160,28 +160,10 @@ public abstract class ExtendableMessageNano<M extends ExtendableMessageNano<M>>
return true;
}
- /**
- * Returns whether the stored unknown field data in this message is equivalent to that in the
- * other message.
- *
- * @param other the other message.
- * @return whether the two sets of unknown field data are equal.
- */
- protected final boolean unknownFieldDataEquals(M other) {
- if (unknownFieldData == null || unknownFieldData.isEmpty()) {
- return other.unknownFieldData == null || other.unknownFieldData.isEmpty();
- } else {
- return unknownFieldData.equals(other.unknownFieldData);
- }
- }
-
- /**
- * Computes the hashcode representing the unknown field data stored in this message.
- *
- * @return the hashcode for the unknown field data.
- */
- protected final int unknownFieldDataHashCode() {
- return (unknownFieldData == null || unknownFieldData.isEmpty()
- ? 0 : unknownFieldData.hashCode());
+ @Override
+ public M clone() throws CloneNotSupportedException {
+ M cloned = (M) super.clone();
+ InternalNano.cloneUnknownFieldData(this, cloned);
+ return cloned;
}
}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/Extension.java b/javanano/src/main/java/com/google/protobuf/nano/Extension.java
index c29b030f..c458f9b1 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/Extension.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/Extension.java
@@ -79,12 +79,30 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
* Should be used by the generated code only.
*
* @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
+ * @deprecated use {@link #createMessageTyped(int, Class, long)} instead.
*/
+ @Deprecated
public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
Extension<M, T> createMessageTyped(int type, Class<T> clazz, int tag) {
return new Extension<M, T>(type, clazz, tag, false);
}
+ // Note: these create...() methods take a long for the tag parameter,
+ // because tags are represented as unsigned ints, and these values exist
+ // in generated code as long values. However, they can fit in 32-bits, so
+ // it's safe to cast them to int without loss of precision.
+
+ /**
+ * Creates an {@code Extension} of the given message type and tag number.
+ * Should be used by the generated code only.
+ *
+ * @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
+ */
+ public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
+ Extension<M, T> createMessageTyped(int type, Class<T> clazz, long tag) {
+ return new Extension<M, T>(type, clazz, (int) tag, false);
+ }
+
/**
* Creates a repeated {@code Extension} of the given message type and tag number.
* Should be used by the generated code only.
@@ -92,8 +110,8 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
* @param type {@link #TYPE_MESSAGE} or {@link #TYPE_GROUP}
*/
public static <M extends ExtendableMessageNano<M>, T extends MessageNano>
- Extension<M, T[]> createRepeatedMessageTyped(int type, Class<T[]> clazz, int tag) {
- return new Extension<M, T[]>(type, clazz, tag, true);
+ Extension<M, T[]> createRepeatedMessageTyped(int type, Class<T[]> clazz, long tag) {
+ return new Extension<M, T[]>(type, clazz, (int) tag, true);
}
/**
@@ -104,8 +122,8 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
* @param clazz the boxed Java type of this extension
*/
public static <M extends ExtendableMessageNano<M>, T>
- Extension<M, T> createPrimitiveTyped(int type, Class<T> clazz, int tag) {
- return new PrimitiveExtension<M, T>(type, clazz, tag, false, 0, 0);
+ Extension<M, T> createPrimitiveTyped(int type, Class<T> clazz, long tag) {
+ return new PrimitiveExtension<M, T>(type, clazz, (int) tag, false, 0, 0);
}
/**
@@ -117,8 +135,9 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
*/
public static <M extends ExtendableMessageNano<M>, T>
Extension<M, T> createRepeatedPrimitiveTyped(
- int type, Class<T> clazz, int tag, int nonPackedTag, int packedTag) {
- return new PrimitiveExtension<M, T>(type, clazz, tag, true, nonPackedTag, packedTag);
+ int type, Class<T> clazz, long tag, long nonPackedTag, long packedTag) {
+ return new PrimitiveExtension<M, T>(type, clazz, (int) tag, true,
+ (int) nonPackedTag, (int) packedTag);
}
/**
@@ -136,7 +155,7 @@ public class Extension<M extends ExtendableMessageNano<M>, T> {
protected final Class<T> clazz;
/**
- * Tag number of this extension.
+ * Tag number of this extension. The data should be viewed as an unsigned 32-bit value.
*/
public final int tag;
diff --git a/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java b/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java
index cdb66da2..eca9c0d9 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/FieldArray.java
@@ -35,9 +35,12 @@ package com.google.protobuf.nano;
* A custom version of {@link android.util.SparseArray} with the minimal API
* for storing {@link FieldData} objects.
*
+ * <p>This class is an internal implementation detail of nano and should not
+ * be called directly by clients.
+ *
* Based on {@link android.support.v4.util.SpareArrayCompat}.
*/
-class FieldArray {
+public final class FieldArray implements Cloneable {
private static final FieldData DELETED = new FieldData();
private boolean mGarbage = false;
@@ -48,7 +51,7 @@ class FieldArray {
/**
* Creates a new FieldArray containing no fields.
*/
- public FieldArray() {
+ FieldArray() {
this(10);
}
@@ -57,7 +60,7 @@ class FieldArray {
* require any additional memory allocation to store the specified
* number of mappings.
*/
- public FieldArray(int initialCapacity) {
+ FieldArray(int initialCapacity) {
initialCapacity = idealIntArraySize(initialCapacity);
mFieldNumbers = new int[initialCapacity];
mData = new FieldData[initialCapacity];
@@ -68,7 +71,7 @@ class FieldArray {
* Gets the FieldData mapped from the specified fieldNumber, or <code>null</code>
* if no such mapping has been made.
*/
- public FieldData get(int fieldNumber) {
+ FieldData get(int fieldNumber) {
int i = binarySearch(fieldNumber);
if (i < 0 || mData[i] == DELETED) {
@@ -81,7 +84,7 @@ class FieldArray {
/**
* Removes the data from the specified fieldNumber, if there was any.
*/
- public void remove(int fieldNumber) {
+ void remove(int fieldNumber) {
int i = binarySearch(fieldNumber);
if (i >= 0 && mData[i] != DELETED) {
@@ -118,7 +121,7 @@ class FieldArray {
* Adds a mapping from the specified fieldNumber to the specified data,
* replacing the previous mapping if there was one.
*/
- public void put(int fieldNumber, FieldData data) {
+ void put(int fieldNumber, FieldData data) {
int i = binarySearch(fieldNumber);
if (i >= 0) {
@@ -167,7 +170,7 @@ class FieldArray {
* Returns the number of key-value mappings that this FieldArray
* currently stores.
*/
- public int size() {
+ int size() {
if (mGarbage) {
gc();
}
@@ -184,7 +187,7 @@ class FieldArray {
* the value from the <code>index</code>th key-value mapping that this
* FieldArray stores.
*/
- public FieldData dataAt(int index) {
+ FieldData dataAt(int index) {
if (mGarbage) {
gc();
}
@@ -270,4 +273,19 @@ class FieldArray {
}
return true;
}
+
+ @Override
+ public final FieldArray clone() {
+ // Trigger GC so we compact and don't copy DELETED elements.
+ int size = size();
+ FieldArray clone = new FieldArray(size);
+ System.arraycopy(mFieldNumbers, 0, clone.mFieldNumbers, 0, size);
+ for (int i = 0; i < size; i++) {
+ if (mData[i] != null) {
+ clone.mData[i] = mData[i].clone();
+ }
+ }
+ clone.mSize = size;
+ return clone;
+ }
}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/FieldData.java b/javanano/src/main/java/com/google/protobuf/nano/FieldData.java
index 21ead88b..ebebabc8 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/FieldData.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/FieldData.java
@@ -39,7 +39,7 @@ import java.util.List;
* Stores unknown fields. These might be extensions or fields that the generated API doesn't
* know about yet.
*/
-class FieldData {
+class FieldData implements Cloneable {
private Extension<?, ?> cachedExtension;
private Object value;
/** The serialised values for this object. Will be cleared if getValue is called */
@@ -187,4 +187,54 @@ class FieldData {
return result;
}
+ @Override
+ public final FieldData clone() {
+ FieldData clone = new FieldData();
+ try {
+ clone.cachedExtension = cachedExtension;
+ if (unknownFieldData == null) {
+ clone.unknownFieldData = null;
+ } else {
+ clone.unknownFieldData.addAll(unknownFieldData);
+ }
+
+ // Whether we need to deep clone value depends on its type. Primitive reference types
+ // (e.g. Integer, Long etc.) are ok, since they're immutable. We need to clone arrays
+ // and messages.
+ if (value == null) {
+ // No cloning required.
+ } else if (value instanceof MessageNano) {
+ clone.value = ((MessageNano) value).clone();
+ } else if (value instanceof byte[]) {
+ clone.value = ((byte[]) value).clone();
+ } else if (value instanceof byte[][]) {
+ byte[][] valueArray = (byte[][]) value;
+ byte[][] cloneArray = new byte[valueArray.length][];
+ clone.value = cloneArray;
+ for (int i = 0; i < valueArray.length; i++) {
+ cloneArray[i] = valueArray[i].clone();
+ }
+ } else if (value instanceof boolean[]) {
+ clone.value = ((boolean[]) value).clone();
+ } else if (value instanceof int[]) {
+ clone.value = ((int[]) value).clone();
+ } else if (value instanceof long[]) {
+ clone.value = ((long[]) value).clone();
+ } else if (value instanceof float[]) {
+ clone.value = ((float[]) value).clone();
+ } else if (value instanceof double[]) {
+ clone.value = ((double[]) value).clone();
+ } else if (value instanceof MessageNano[]) {
+ MessageNano[] valueArray = (MessageNano[]) value;
+ MessageNano[] cloneArray = new MessageNano[valueArray.length];
+ clone.value = cloneArray;
+ for (int i = 0; i < valueArray.length; i++) {
+ cloneArray[i] = valueArray[i].clone();
+ }
+ }
+ return clone;
+ } catch (CloneNotSupportedException e) {
+ throw new AssertionError(e);
+ }
+ }
}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
index e7ba8d12..f1263df5 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/InternalNano.java
@@ -536,4 +536,12 @@ public final class InternalNano {
}
return o.hashCode();
}
+
+ // This avoids having to make FieldArray public.
+ public static void cloneUnknownFieldData(ExtendableMessageNano original,
+ ExtendableMessageNano cloned) {
+ if (original.unknownFieldData != null) {
+ cloned.unknownFieldData = (FieldArray) original.unknownFieldData.clone();
+ }
+ }
}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java b/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java
index 81e58571..23475027 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/MessageNano.java
@@ -187,4 +187,12 @@ public abstract class MessageNano {
public String toString() {
return MessageNanoPrinter.print(this);
}
+
+ /**
+ * Provides support for cloning. This only works if you specify the generate_clone method.
+ */
+ @Override
+ public MessageNano clone() throws CloneNotSupportedException {
+ return (MessageNano) super.clone();
+ }
}
diff --git a/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java b/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
index c4b2ad3d..d9500bb9 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/MessageNanoPrinter.java
@@ -109,6 +109,10 @@ public final class MessageNanoPrinter {
for (Field field : clazz.getFields()) {
int modifiers = field.getModifiers();
String fieldName = field.getName();
+ if ("cachedSize".equals(fieldName)) {
+ // TODO(bduff): perhaps cachedSize should have a more obscure name.
+ continue;
+ }
if ((modifiers & Modifier.PUBLIC) == Modifier.PUBLIC
&& (modifiers & Modifier.STATIC) != Modifier.STATIC
diff --git a/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java b/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java
index a17fccf3..b1678d1b 100644
--- a/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java
+++ b/javanano/src/main/java/com/google/protobuf/nano/UnknownFieldData.java
@@ -42,6 +42,10 @@ import java.util.Arrays;
final class UnknownFieldData {
final int tag;
+ /**
+ * Important: this should be treated as immutable, even though it's possible
+ * to change the array values.
+ */
final byte[] bytes;
UnknownFieldData(int tag, byte[] bytes) {
diff --git a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
index 7de84310..3a75777a 100644
--- a/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
+++ b/javanano/src/test/java/com/google/protobuf/nano/NanoTest.java
@@ -31,11 +31,13 @@
package com.google.protobuf.nano;
import com.google.protobuf.nano.MapTestProto.TestMap;
+import com.google.protobuf.nano.CodedOutputByteBufferNano;
import com.google.protobuf.nano.MapTestProto.TestMap.MessageValue;
import com.google.protobuf.nano.NanoAccessorsOuterClass.TestNanoAccessors;
import com.google.protobuf.nano.NanoHasOuterClass.TestAllTypesNanoHas;
import com.google.protobuf.nano.NanoOuterClass.TestAllTypesNano;
import com.google.protobuf.nano.UnittestRecursiveNano.RecursiveMessageNano;
+import com.google.protobuf.nano.NanoReferenceTypesCompat;
import com.google.protobuf.nano.UnittestSimpleNano.SimpleMessageNano;
import com.google.protobuf.nano.UnittestSingleNano.SingleMessageNano;
import com.google.protobuf.nano.testext.Extensions;
@@ -2300,6 +2302,59 @@ public class NanoTest extends TestCase {
}
}
+ public void testDifferentStringLengthsNano() throws Exception {
+ // Test string serialization roundtrip using strings of the following lengths,
+ // with ASCII and Unicode characters requiring different UTF-8 byte counts per
+ // char, hence causing the length delimiter varint to sometimes require more
+ // bytes for the Unicode strings than the ASCII string of the same length.
+ int[] lengths = new int[] {
+ 0,
+ 1,
+ (1 << 4) - 1, // 1 byte for ASCII and Unicode
+ (1 << 7) - 1, // 1 byte for ASCII, 2 bytes for Unicode
+ (1 << 11) - 1, // 2 bytes for ASCII and Unicode
+ (1 << 14) - 1, // 2 bytes for ASCII, 3 bytes for Unicode
+ (1 << 17) - 1, // 3 bytes for ASCII and Unicode
+ };
+ for (int i : lengths) {
+ testEncodingOfString('q', i); // 1 byte per char
+ testEncodingOfString('\u07FF', i); // 2 bytes per char
+ testEncodingOfString('\u0981', i); // 3 bytes per char
+ }
+ }
+
+ /** Regression test for https://github.com/google/protobuf/issues/292 */
+ public void testCorrectExceptionThrowWhenEncodingStringsWithoutEnoughSpace() throws Exception {
+ String testCase = "Foooooooo";
+ assertEquals(CodedOutputByteBufferNano.computeRawVarint32Size(testCase.length()),
+ CodedOutputByteBufferNano.computeRawVarint32Size(testCase.length() * 3));
+ assertEquals(11, CodedOutputByteBufferNano.computeStringSize(1, testCase));
+ // Tag is one byte, varint describing string length is 1 byte, string length is 9 bytes.
+ // An array of size 1 will cause a failure when trying to write the varint.
+ for (int i = 0; i < 11; i++) {
+ CodedOutputByteBufferNano bufferNano = CodedOutputByteBufferNano.newInstance(new byte[i]);
+ try {
+ bufferNano.writeString(1, testCase);
+ fail("Should have thrown an out of space exception");
+ } catch (CodedOutputByteBufferNano.OutOfSpaceException expected) {}
+ }
+ }
+
+ private void testEncodingOfString(char c, int length) throws InvalidProtocolBufferNanoException {
+ TestAllTypesNano testAllTypesNano = new TestAllTypesNano();
+ final String fullString = fullString(c, length);
+ testAllTypesNano.optionalString = fullString;
+ final TestAllTypesNano resultNano = new TestAllTypesNano();
+ MessageNano.mergeFrom(resultNano, MessageNano.toByteArray(testAllTypesNano));
+ assertEquals(fullString, resultNano.optionalString);
+ }
+
+ private String fullString(char c, int length) {
+ char[] result = new char[length];
+ Arrays.fill(result, c);
+ return new String(result);
+ }
+
public void testNanoWithHasParseFrom() throws Exception {
TestAllTypesNanoHas msg = null;
// Test false on creation, after clear and upon empty parse.
@@ -2986,6 +3041,10 @@ public class NanoTest extends TestCase {
assertTrue(Arrays.equals(floats, message.getExtension(RepeatedExtensions.repeatedFloat)));
assertTrue(Arrays.equals(doubles, message.getExtension(RepeatedExtensions.repeatedDouble)));
assertTrue(Arrays.equals(enums, message.getExtension(RepeatedExtensions.repeatedEnum)));
+
+ // Clone the message and ensure it's still equal.
+ Extensions.ExtendableMessage clone = message.clone();
+ assertEquals(clone, message);
}
public void testNullExtensions() throws Exception {
@@ -4345,6 +4404,11 @@ public class NanoTest extends TestCase {
assertMapSet(testMap.sfixed64ToSfixed64Field, int64Values, int64Values);
}
+ public void testRepeatedFieldInitializedInReftypesCompatMode() {
+ NanoReferenceTypesCompat.TestAllTypesNano proto = new NanoReferenceTypesCompat.TestAllTypesNano();
+ assertNotNull(proto.repeatedString);
+ }
+
private void assertRepeatedPackablesEqual(
NanoRepeatedPackables.NonPacked nonPacked, NanoRepeatedPackables.Packed packed) {
// Not using MessageNano.equals() -- that belongs to a separate test.
@@ -4364,6 +4428,22 @@ public class NanoTest extends TestCase {
assertTrue(Arrays.equals(nonPacked.enums, packed.enums));
}
+ public void testClone() throws Exception {
+ // A simple message.
+ AnotherMessage anotherMessage = new AnotherMessage();
+ anotherMessage.string = "Hello";
+ anotherMessage.value = true;
+ anotherMessage.integers = new int[] { 1, 2, 3 };
+
+ AnotherMessage clone = anotherMessage.clone();
+ assertEquals(clone, anotherMessage);
+
+ // Verify it was a deep clone - changes to the clone shouldn't affect the
+ // original.
+ clone.integers[1] = 100;
+ assertFalse(clone.equals(anotherMessage));
+ }
+
private void assertHasWireData(MessageNano message, boolean expected) {
byte[] bytes = MessageNano.toByteArray(message);
int wireLength = bytes.length;
diff --git a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto b/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto
index 2a678a80..ca56b3dd 100644
--- a/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto
+++ b/javanano/src/test/java/com/google/protobuf/nano/unittest_extension_nano.proto
@@ -16,11 +16,15 @@ enum AnEnum {
message AnotherMessage {
optional string string = 1;
optional bool value = 2;
+ repeated int32 integers = 3;
}
message ContainerMessage {
extend ExtendableMessage {
optional bool another_thing = 100;
+ // The largest permitted field number, per
+ // https://developers.google.com/protocol-buffers/docs/proto#simple
+ optional bool large_field_number = 536870911;
}
}
diff --git a/objectivec/DevTools/check_version_stamps.sh b/objectivec/DevTools/check_version_stamps.sh
new file mode 100755
index 00000000..5de9ef14
--- /dev/null
+++ b/objectivec/DevTools/check_version_stamps.sh
@@ -0,0 +1,56 @@
+#!/bin/bash
+
+# This script checks that the runtime version number constant in the compiler
+# source and in the runtime source is the same.
+#
+# A distro can be made of the protobuf sources with only a subset of the
+# languages, so if the compiler depended on the Objective C runtime, those
+# builds would break. At the same time, we don't want the runtime source
+# depending on the compiler sources; so two copies of the constant are needed.
+
+set -eu
+
+readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")")
+readonly ProtoRootDir="${ScriptDir}/../.."
+
+die() {
+ echo "Error: $1"
+ exit 1
+}
+
+readonly ConstantName=GOOGLE_PROTOBUF_OBJC_GEN_VERSION
+
+# Collect version from plugin sources.
+
+readonly PluginSrc="${ProtoRootDir}/src/google/protobuf/compiler/objectivec/objectivec_file.cc"
+readonly PluginVersion=$( \
+ cat "${PluginSrc}" \
+ | sed -n -e "s:const int32_t ${ConstantName} = \([0-9]*\);:\1:p"
+)
+
+if [[ -z "${PluginVersion}" ]] ; then
+ die "Failed to fine ${ConstantName} in the plugin source (${PluginSrc})."
+fi
+
+# Collect version from runtime sources.
+
+readonly RuntimeSrc="${ProtoRootDir}/objectivec/GPBBootstrap.h"
+readonly RuntimeVersion=$( \
+ cat "${RuntimeSrc}" \
+ | sed -n -e "s:#define ${ConstantName} \([0-9]*\):\1:p"
+)
+
+if [[ -z "${RuntimeVersion}" ]] ; then
+ die "Failed to fine ${ConstantName} in the runtime source (${RuntimeSrc})."
+fi
+
+# Compare them.
+
+if [[ "${PluginVersion}" != "${RuntimeVersion}" ]] ; then
+ die "Versions don't match!
+ Plugin: ${PluginVersion} from ${PluginSrc}
+ Runtime: ${RuntimeVersion} from ${RuntimeSrc}
+"
+fi
+
+# Success
diff --git a/objectivec/DevTools/generate_descriptors_proto.sh b/objectivec/DevTools/generate_descriptors_proto.sh
new file mode 100755
index 00000000..42502bfe
--- /dev/null
+++ b/objectivec/DevTools/generate_descriptors_proto.sh
@@ -0,0 +1,36 @@
+#!/bin/bash
+
+# This script will generate the common descriptors needed by the Objective C
+# runtime.
+
+# HINT: Flags passed to generate_descriptor_proto.sh will be passed directly
+# to make when building protoc. This is particularly useful for passing
+# -j4 to run 4 jobs simultaneously.
+
+set -eu
+
+readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")")
+readonly ProtoRootDir="${ScriptDir}/../.."
+readonly ProtoC="${ProtoRootDir}/src/protoc"
+
+pushd "${ProtoRootDir}" > /dev/null
+
+# Compiler build fails if config.h hasn't been made yet (even if configure/etc.
+# have been run, so get that made first).
+make $@ config.h
+
+# Make sure the compiler is current.
+cd src
+make $@ protoc
+
+# These really should only be run when the inputs or compiler are newer than
+# the outputs.
+
+# Needed by the runtime.
+./protoc --objc_out="${ProtoRootDir}/objectivec" google/protobuf/descriptor.proto
+
+# Well known types that the library provides helpers for.
+./protoc --objc_out="${ProtoRootDir}/objectivec" google/protobuf/timestamp.proto
+./protoc --objc_out="${ProtoRootDir}/objectivec" google/protobuf/duration.proto
+
+popd > /dev/null
diff --git a/objectivec/DevTools/pddm.py b/objectivec/DevTools/pddm.py
new file mode 100755
index 00000000..d1b53f5a
--- /dev/null
+++ b/objectivec/DevTools/pddm.py
@@ -0,0 +1,687 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2015 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.
+
+"""PDDM - Poor Developers' Debug-able Macros
+
+A simple markup that can be added in comments of source so they can then be
+expanded out into code. Most of this could be done with CPP macros, but then
+developers can't really step through them in the debugger, this way they are
+expanded to the same code, but you can debug them.
+
+Any file can be processed, but the syntax is designed around a C based compiler.
+Processed lines start with "//%". There are three types of sections you can
+create: Text (left alone), Macro Definitions, and Macro Expansions. There is
+no order required between definitions and expansions, all definitions are read
+before any expansions are processed (thus, if desired, definitions can be put
+at the end of the file to keep them out of the way of the code).
+
+Macro Definitions are started with "//%PDDM-DEFINE Name(args)" and all lines
+afterwards that start with "//%" are included in the definition. Multiple
+macros can be defined in one block by just using a another "//%PDDM-DEFINE"
+line to start the next macro. Optionally, a macro can be ended with
+"//%PDDM-DEFINE-END", this can be useful when you want to make it clear that
+trailing blank lines are included in the macro. You can also end a definition
+with an expansion.
+
+Macro Expansions are started by single lines containing
+"//%PDDM-EXPAND Name(args)" and then with "//%PDDM-EXPAND-END" or another
+expansions. All lines in-between are replaced by the result of the expansion.
+The first line of the expansion is always a blank like just for readability.
+
+Expansion itself is pretty simple, one macro can invoke another macro, but
+you cannot nest the invoke of a macro in another macro (i.e. - can't do
+"foo(bar(a))", but you can define foo(a) and bar(b) where bar invokes foo()
+within its expansion.
+
+When macros are expanded, the arg references can also add "$O" suffix to the
+name (i.e. - "NAME$O") to specify an option to be applied. The options are:
+
+ $S - Replace each character in the value with a space.
+ $l - Lowercase the first letter of the value.
+ $L - Lowercase the whole value.
+ $u - Uppercase the first letter of the value.
+ $U - Uppercase the whole value.
+
+Within a macro you can use ## to cause things to get joined together after
+expansion (i.e. - "a##b" within a macro will become "ab").
+
+Example:
+
+ int foo(MyEnum x) {
+ switch (x) {
+ //%PDDM-EXPAND case(Enum_Left, 1)
+ //%PDDM-EXPAND case(Enum_Center, 2)
+ //%PDDM-EXPAND case(Enum_Right, 3)
+ //%PDDM-EXPAND-END
+ }
+
+ //%PDDM-DEFINE case(_A, _B)
+ //% case _A:
+ //% return _B;
+
+ A macro ends at the start of the next one, or an optional %PDDM-DEFINE-END
+ can be used to avoid adding extra blank lines/returns (or make it clear when
+ it is desired).
+
+ One macro can invoke another by simply using its name NAME(ARGS). You cannot
+ nest an invoke inside another (i.e. - NAME1(NAME2(ARGS)) isn't supported).
+
+ Within a macro you can use ## to cause things to get joined together after
+ processing (i.e. - "a##b" within a macro will become "ab").
+
+
+"""
+
+import optparse
+import os
+import re
+import sys
+
+
+# Regex for macro definition.
+_MACRO_RE = re.compile(r'(?P<name>\w+)\((?P<args>.*?)\)')
+# Regex for macro's argument definition.
+_MACRO_ARG_NAME_RE = re.compile(r'^\w+$')
+
+# Line inserted after each EXPAND.
+_GENERATED_CODE_LINE = (
+ '// This block of code is generated, do not edit it directly.'
+)
+
+
+def _MacroRefRe(macro_names):
+ # Takes in a list of macro names and makes a regex that will match invokes
+ # of those macros.
+ return re.compile(r'\b(?P<macro_ref>(?P<name>(%s))\((?P<args>.*?)\))' %
+ '|'.join(macro_names))
+
+def _MacroArgRefRe(macro_arg_names):
+ # Takes in a list of macro arg names and makes a regex that will match
+ # uses of those args.
+ return re.compile(r'\b(?P<name>(%s))(\$(?P<option>.))?\b' %
+ '|'.join(macro_arg_names))
+
+
+class PDDMError(Exception):
+ """Error thrown by pddm."""
+ pass
+
+
+class MacroCollection(object):
+ """Hold a set of macros and can resolve/expand them."""
+
+ def __init__(self, a_file=None):
+ """Initializes the collection.
+
+ Args:
+ a_file: The file like stream to parse.
+
+ Raises:
+ PDDMError if there are any issues.
+ """
+ self._macros = dict()
+ if a_file:
+ self.ParseInput(a_file)
+
+ class MacroDefinition(object):
+ """Holds a macro definition."""
+
+ def __init__(self, name, arg_names):
+ self._name = name
+ self._args = tuple(arg_names)
+ self._body = ''
+ self._needNewLine = False
+
+ def AppendLine(self, line):
+ if self._needNewLine:
+ self._body += '\n'
+ self._body += line
+ self._needNewLine = not line.endswith('\n')
+
+ @property
+ def name(self):
+ return self._name
+
+ @property
+ def args(self):
+ return self._args
+
+ @property
+ def body(self):
+ return self._body
+
+ def ParseInput(self, a_file):
+ """Consumes input extracting definitions.
+
+ Args:
+ a_file: The file like stream to parse.
+
+ Raises:
+ PDDMError if there are any issues.
+ """
+ input_lines = a_file.read().splitlines()
+ self.ParseLines(input_lines)
+
+ def ParseLines(self, input_lines):
+ """Parses list of lines.
+
+ Args:
+ input_lines: A list of strings of input to parse (no newlines on the
+ strings).
+
+ Raises:
+ PDDMError if there are any issues.
+ """
+ current_macro = None
+ for line in input_lines:
+ if line.startswith('PDDM-'):
+ directive = line.split(' ', 1)[0]
+ if directive == 'PDDM-DEFINE':
+ name, args = self._ParseDefineLine(line)
+ if self._macros.get(name):
+ raise PDDMError('Attempt to redefine macro: "%s"' % line)
+ current_macro = self.MacroDefinition(name, args)
+ self._macros[name] = current_macro
+ continue
+ if directive == 'PDDM-DEFINE-END':
+ if not current_macro:
+ raise PDDMError('Got DEFINE-END directive without an active macro:'
+ ' "%s"' % line)
+ current_macro = None
+ continue
+ raise PDDMError('Hit a line with an unknown directive: "%s"' % line)
+
+ if current_macro:
+ current_macro.AppendLine(line)
+ continue
+
+ # Allow blank lines between macro definitions.
+ if line.strip() == '':
+ continue
+
+ raise PDDMError('Hit a line that wasn\'t a directive and no open macro'
+ ' definition: "%s"' % line)
+
+ def _ParseDefineLine(self, input_line):
+ assert input_line.startswith('PDDM-DEFINE')
+ line = input_line[12:].strip()
+ match = _MACRO_RE.match(line)
+ # Must match full line
+ if match is None or match.group(0) != line:
+ raise PDDMError('Failed to parse macro definition: "%s"' % input_line)
+ name = match.group('name')
+ args_str = match.group('args').strip()
+ args = []
+ if args_str:
+ for part in args_str.split(','):
+ arg = part.strip()
+ if arg == '':
+ raise PDDMError('Empty arg name in macro definition: "%s"'
+ % input_line)
+ if not _MACRO_ARG_NAME_RE.match(arg):
+ raise PDDMError('Invalid arg name "%s" in macro definition: "%s"'
+ % (arg, input_line))
+ if arg in args:
+ raise PDDMError('Arg name "%s" used more than once in macro'
+ ' definition: "%s"' % (arg, input_line))
+ args.append(arg)
+ return (name, tuple(args))
+
+ def Expand(self, macro_ref_str):
+ """Expands the macro reference.
+
+ Args:
+ macro_ref_str: String of a macro reference (i.e. foo(a, b)).
+
+ Returns:
+ The text from the expansion.
+
+ Raises:
+ PDDMError if there are any issues.
+ """
+ match = _MACRO_RE.match(macro_ref_str)
+ if match is None or match.group(0) != macro_ref_str:
+ raise PDDMError('Failed to parse macro reference: "%s"' % macro_ref_str)
+ if match.group('name') not in self._macros:
+ raise PDDMError('No macro named "%s".' % match.group('name'))
+ return self._Expand(match, [], macro_ref_str)
+
+ def _FormatStack(self, macro_ref_stack):
+ result = ''
+ for _, macro_ref in reversed(macro_ref_stack):
+ result += '\n...while expanding "%s".' % macro_ref
+ return result
+
+ def _Expand(self, macro_ref_match, macro_stack, macro_ref_str=None):
+ if macro_ref_str is None:
+ macro_ref_str = macro_ref_match.group('macro_ref')
+ name = macro_ref_match.group('name')
+ for prev_name, prev_macro_ref in macro_stack:
+ if name == prev_name:
+ raise PDDMError('Found macro recusion, invoking "%s":%s' %
+ (macro_ref_str, self._FormatStack(macro_stack)))
+ macro = self._macros[name]
+ args_str = macro_ref_match.group('args').strip()
+ args = []
+ if args_str or len(macro.args):
+ args = [x.strip() for x in args_str.split(',')]
+ if len(args) != len(macro.args):
+ raise PDDMError('Expected %d args, got: "%s".%s' %
+ (len(macro.args), macro_ref_str,
+ self._FormatStack(macro_stack)))
+ # Replace args usages.
+ result = self._ReplaceArgValues(macro, args, macro_ref_str, macro_stack)
+ # Expand any macro invokes.
+ new_macro_stack = macro_stack + [(name, macro_ref_str)]
+ while True:
+ eval_result = self._EvalMacrosRefs(result, new_macro_stack)
+ # Consume all ## directives to glue things together.
+ eval_result = eval_result.replace('##', '')
+ if eval_result == result:
+ break
+ result = eval_result
+ return result
+
+ def _ReplaceArgValues(self,
+ macro, arg_values, macro_ref_to_report, macro_stack):
+ if len(arg_values) == 0:
+ # Nothing to do
+ return macro.body
+ assert len(arg_values) == len(macro.args)
+ args = dict(zip(macro.args, arg_values))
+ def _lookupArg(match):
+ val = args[match.group('name')]
+ opt = match.group('option')
+ if opt:
+ if opt == 'S': # Spaces for the length
+ return ' ' * len(val)
+ elif opt == 'l': # Lowercase first character
+ if val:
+ return val[0].lower() + val[1:]
+ else:
+ return val
+ elif opt == 'L': # All Lowercase
+ return val.lower()
+ elif opt == 'u': # Uppercase first character
+ if val:
+ return val[0].upper() + val[1:]
+ else:
+ return val
+ elif opt == 'U': # All Uppercase
+ return val.upper()
+ else:
+ raise PDDMError('Unknown arg option "%s$%s" while expanding "%s".%s'
+ % (match.group('name'), match.group('option'),
+ macro_ref_to_report,
+ self._FormatStack(macro_stack)))
+ return val
+ # Let the regex do the work!
+ macro_arg_ref_re = _MacroArgRefRe(macro.args)
+ return macro_arg_ref_re.sub(_lookupArg, macro.body)
+
+ def _EvalMacrosRefs(self, text, macro_stack):
+ macro_ref_re = _MacroRefRe(self._macros.keys())
+ def _resolveMacro(match):
+ return self._Expand(match, macro_stack)
+ return macro_ref_re.sub(_resolveMacro, text)
+
+
+class SourceFile(object):
+ """Represents a source file with PDDM directives in it."""
+
+ def __init__(self, a_file, import_resolver=None):
+ """Initializes the file reading in the file.
+
+ Args:
+ a_file: The file to read in.
+ import_resolver: a function that given a path will return a stream for
+ the contents.
+
+ Raises:
+ PDDMError if there are any issues.
+ """
+ self._sections = []
+ self._original_content = a_file.read()
+ self._import_resolver = import_resolver
+ self._processed_content = None
+
+ class SectionBase(object):
+
+ def __init__(self, first_line_num):
+ self._lines = []
+ self._first_line_num = first_line_num
+
+ def TryAppend(self, line, line_num):
+ """Try appending a line.
+
+ Args:
+ line: The line to append.
+ line_num: The number of the line.
+
+ Returns:
+ A tuple of (SUCCESS, CAN_ADD_MORE). If SUCCESS if False, the line
+ wasn't append. If SUCCESS is True, then CAN_ADD_MORE is True/False to
+ indicate if more lines can be added after this one.
+ """
+ assert False, "sublcass should have overridden"
+ return (False, False)
+
+ def HitEOF(self):
+ """Called when the EOF was reached for for a given section."""
+ pass
+
+ def BindMacroCollection(self, macro_collection):
+ """Binds the chunk to a macro collection.
+
+ Args:
+ macro_collection: The collection to bind too.
+ """
+ pass
+
+ def Append(self, line):
+ self._lines.append(line)
+
+ @property
+ def lines(self):
+ return self._lines
+
+ @property
+ def num_lines_captured(self):
+ return len(self._lines)
+
+ @property
+ def first_line_num(self):
+ return self._first_line_num
+
+ @property
+ def first_line(self):
+ if not self._lines:
+ return ''
+ return self._lines[0]
+
+ @property
+ def text(self):
+ return '\n'.join(self.lines) + '\n'
+
+ class TextSection(SectionBase):
+ """Text section that is echoed out as is."""
+
+ def TryAppend(self, line, line_num):
+ if line.startswith('//%PDDM'):
+ return (False, False)
+ self.Append(line)
+ return (True, True)
+
+ class ExpansionSection(SectionBase):
+ """Section that is the result of an macro expansion."""
+
+ def __init__(self, first_line_num):
+ SourceFile.SectionBase.__init__(self, first_line_num)
+ self._macro_collection = None
+
+ def TryAppend(self, line, line_num):
+ if line.startswith('//%PDDM'):
+ directive = line.split(' ', 1)[0]
+ if directive == '//%PDDM-EXPAND':
+ self.Append(line)
+ return (True, True)
+ if directive == '//%PDDM-EXPAND-END':
+ assert self.num_lines_captured > 0
+ return (True, False)
+ raise PDDMError('Ran into directive ("%s", line %d) while in "%s".' %
+ (directive, line_num, self.first_line))
+ # Eat other lines.
+ return (True, True)
+
+ def HitEOF(self):
+ raise PDDMError('Hit the end of the file while in "%s".' %
+ self.first_line)
+
+ def BindMacroCollection(self, macro_collection):
+ self._macro_collection = macro_collection
+
+ @property
+ def lines(self):
+ captured_lines = SourceFile.SectionBase.lines.fget(self)
+ directive_len = len('//%PDDM-EXPAND')
+ result = []
+ for line in captured_lines:
+ result.append(line)
+ if self._macro_collection:
+ # Always add a blank line, seems to read better. (If need be, add an
+ # option to the EXPAND to indicate if this should be done.)
+ result.extend([_GENERATED_CODE_LINE, ''])
+ macro = line[directive_len:].strip()
+ try:
+ expand_result = self._macro_collection.Expand(macro)
+ # Since expansions are line oriented, strip trailing whitespace
+ # from the lines.
+ lines = [x.rstrip() for x in expand_result.split('\n')]
+ result.append('\n'.join(lines))
+ except PDDMError as e:
+ raise PDDMError('%s\n...while expanding "%s" from the section'
+ ' that started:\n Line %d: %s' %
+ (e.message, macro,
+ self.first_line_num, self.first_line))
+
+ # Add the ending marker.
+ if len(captured_lines) == 1:
+ result.append('//%%PDDM-EXPAND-END %s' %
+ captured_lines[0][directive_len:].strip())
+ else:
+ result.append('//%%PDDM-EXPAND-END (%s expansions)' % len(captured_lines))
+
+ return result
+
+ class DefinitionSection(SectionBase):
+ """Section containing macro definitions"""
+
+ def TryAppend(self, line, line_num):
+ if not line.startswith('//%'):
+ return (False, False)
+ if line.startswith('//%PDDM'):
+ directive = line.split(' ', 1)[0]
+ if directive == "//%PDDM-EXPAND":
+ return False, False
+ if directive not in ('//%PDDM-DEFINE', '//%PDDM-DEFINE-END'):
+ raise PDDMError('Ran into directive ("%s", line %d) while in "%s".' %
+ (directive, line_num, self.first_line))
+ self.Append(line)
+ return (True, True)
+
+ def BindMacroCollection(self, macro_collection):
+ if macro_collection:
+ try:
+ # Parse the lines after stripping the prefix.
+ macro_collection.ParseLines([x[3:] for x in self.lines])
+ except PDDMError as e:
+ raise PDDMError('%s\n...while parsing section that started:\n'
+ ' Line %d: %s' %
+ (e.message, self.first_line_num, self.first_line))
+
+ class ImportDefinesSection(SectionBase):
+ """Section containing an import of PDDM-DEFINES from an external file."""
+
+ def __init__(self, first_line_num, import_resolver):
+ SourceFile.SectionBase.__init__(self, first_line_num)
+ self._import_resolver = import_resolver
+
+ def TryAppend(self, line, line_num):
+ if not line.startswith('//%PDDM-IMPORT-DEFINES '):
+ return (False, False)
+ assert self.num_lines_captured == 0
+ self.Append(line)
+ return (True, False)
+
+ def BindMacroCollection(self, macro_colletion):
+ if not macro_colletion:
+ return
+ if self._import_resolver is None:
+ raise PDDMError('Got an IMPORT-DEFINES without a resolver (line %d):'
+ ' "%s".' % (self.first_line_num, self.first_line))
+ import_name = self.first_line.split(' ', 1)[1].strip()
+ imported_file = self._import_resolver(import_name)
+ if imported_file is None:
+ raise PDDMError('Resolver failed to find "%s" (line %d):'
+ ' "%s".' %
+ (import_name, self.first_line_num, self.first_line))
+ try:
+ imported_src_file = SourceFile(imported_file, self._import_resolver)
+ imported_src_file._ParseFile()
+ for section in imported_src_file._sections:
+ section.BindMacroCollection(macro_colletion)
+ except PDDMError as e:
+ raise PDDMError('%s\n...while importing defines:\n'
+ ' Line %d: %s' %
+ (e.message, self.first_line_num, self.first_line))
+
+ def _ParseFile(self):
+ self._sections = []
+ lines = self._original_content.splitlines()
+ cur_section = None
+ for line_num, line in enumerate(lines, 1):
+ if not cur_section:
+ cur_section = self._MakeSection(line, line_num)
+ was_added, accept_more = cur_section.TryAppend(line, line_num)
+ if not was_added:
+ cur_section = self._MakeSection(line, line_num)
+ was_added, accept_more = cur_section.TryAppend(line, line_num)
+ assert was_added
+ if not accept_more:
+ cur_section = None
+
+ if cur_section:
+ cur_section.HitEOF()
+
+ def _MakeSection(self, line, line_num):
+ if not line.startswith('//%PDDM'):
+ section = self.TextSection(line_num)
+ else:
+ directive = line.split(' ', 1)[0]
+ if directive == '//%PDDM-EXPAND':
+ section = self.ExpansionSection(line_num)
+ elif directive == '//%PDDM-DEFINE':
+ section = self.DefinitionSection(line_num)
+ elif directive == '//%PDDM-IMPORT-DEFINES':
+ section = self.ImportDefinesSection(line_num, self._import_resolver)
+ else:
+ raise PDDMError('Unexpected line %d: "%s".' % (line_num, line))
+ self._sections.append(section)
+ return section
+
+ def ProcessContent(self, strip_expansion=False):
+ """Processes the file contents."""
+ self._ParseFile()
+ if strip_expansion:
+ # Without a collection the expansions become blank, removing them.
+ collection = None
+ else:
+ collection = MacroCollection()
+ for section in self._sections:
+ section.BindMacroCollection(collection)
+ result = ''
+ for section in self._sections:
+ result += section.text
+ self._processed_content = result
+
+ @property
+ def original_content(self):
+ return self._original_content
+
+ @property
+ def processed_content(self):
+ return self._processed_content
+
+
+def main(args):
+ usage = '%prog [OPTIONS] PATH ...'
+ description = (
+ 'Processes PDDM directives in the the given paths and write them back'
+ ' out.'
+ )
+ parser = optparse.OptionParser(usage=usage, description=description)
+ parser.add_option('--dry-run',
+ default=False, action='store_true',
+ help='Don\'t write back to the file(s), just report if the'
+ ' contents needs an update and exit with a value of 1.')
+ parser.add_option('--verbose',
+ default=False, action='store_true',
+ help='Reports is a file is already current.')
+ parser.add_option('--collapse',
+ default=False, action='store_true',
+ help='Removes all the generated code.')
+ opts, extra_args = parser.parse_args(args)
+
+ if not extra_args:
+ parser.error('Need atleast one file to process')
+
+ result = 0
+ for a_path in extra_args:
+ if not os.path.exists(a_path):
+ sys.stderr.write('ERROR: File not found: %s\n' % a_path)
+ return 100
+
+ def _ImportResolver(name):
+ # resolve based on the file being read.
+ a_dir = os.path.dirname(a_path)
+ import_path = os.path.join(a_dir, name)
+ if not os.path.exists(import_path):
+ return None
+ return open(import_path, 'r')
+
+ with open(a_path, 'r') as f:
+ src_file = SourceFile(f, _ImportResolver)
+
+ try:
+ src_file.ProcessContent(strip_expansion=opts.collapse)
+ except PDDMError as e:
+ sys.stderr.write('ERROR: %s\n...While processing "%s"\n' %
+ (e.message, a_path))
+ return 101
+
+ if src_file.processed_content != src_file.original_content:
+ if not opts.dry_run:
+ print 'Updating for "%s".' % a_path
+ with open(a_path, 'w') as f:
+ f.write(src_file.processed_content)
+ else:
+ # Special result to indicate things need updating.
+ print 'Update needed for "%s".' % a_path
+ result = 1
+ elif opts.verbose:
+ print 'No update for "%s".' % a_path
+
+ return result
+
+
+if __name__ == '__main__':
+ sys.exit(main(sys.argv[1:]))
diff --git a/objectivec/DevTools/pddm_tests.py b/objectivec/DevTools/pddm_tests.py
new file mode 100755
index 00000000..8a73b842
--- /dev/null
+++ b/objectivec/DevTools/pddm_tests.py
@@ -0,0 +1,515 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2015 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.
+
+"""Tests for pddm.py."""
+
+import io
+import unittest
+
+import pddm
+
+
+class TestParsingMacros(unittest.TestCase):
+
+ def testParseEmpty(self):
+ f = io.StringIO(u'')
+ result = pddm.MacroCollection(f)
+ self.assertEqual(len(result._macros), 0)
+
+ def testParseOne(self):
+ f = io.StringIO(u"""PDDM-DEFINE foo( )
+body""")
+ result = pddm.MacroCollection(f)
+ self.assertEqual(len(result._macros), 1)
+ macro = result._macros.get('foo')
+ self.assertIsNotNone(macro)
+ self.assertEquals(macro.name, 'foo')
+ self.assertEquals(macro.args, tuple())
+ self.assertEquals(macro.body, 'body')
+
+ def testParseGeneral(self):
+ # Tests multiple defines, spaces in all places, etc.
+ f = io.StringIO(u"""
+PDDM-DEFINE noArgs( )
+body1
+body2
+
+PDDM-DEFINE-END
+
+PDDM-DEFINE oneArg(foo)
+body3
+PDDM-DEFINE twoArgs( bar_ , baz )
+body4
+body5""")
+ result = pddm.MacroCollection(f)
+ self.assertEqual(len(result._macros), 3)
+ macro = result._macros.get('noArgs')
+ self.assertIsNotNone(macro)
+ self.assertEquals(macro.name, 'noArgs')
+ self.assertEquals(macro.args, tuple())
+ self.assertEquals(macro.body, 'body1\nbody2\n')
+ macro = result._macros.get('oneArg')
+ self.assertIsNotNone(macro)
+ self.assertEquals(macro.name, 'oneArg')
+ self.assertEquals(macro.args, ('foo',))
+ self.assertEquals(macro.body, 'body3')
+ macro = result._macros.get('twoArgs')
+ self.assertIsNotNone(macro)
+ self.assertEquals(macro.name, 'twoArgs')
+ self.assertEquals(macro.args, ('bar_', 'baz'))
+ self.assertEquals(macro.body, 'body4\nbody5')
+ # Add into existing collection
+ f = io.StringIO(u"""
+PDDM-DEFINE another(a,b,c)
+body1
+body2""")
+ result.ParseInput(f)
+ self.assertEqual(len(result._macros), 4)
+ macro = result._macros.get('another')
+ self.assertIsNotNone(macro)
+ self.assertEquals(macro.name, 'another')
+ self.assertEquals(macro.args, ('a', 'b', 'c'))
+ self.assertEquals(macro.body, 'body1\nbody2')
+
+ def testParseDirectiveIssues(self):
+ test_list = [
+ # Unknown directive
+ (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINED foo\nbaz',
+ 'Hit a line with an unknown directive: '),
+ # End without begin
+ (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nPDDM-DEFINE-END\n',
+ 'Got DEFINE-END directive without an active macro: '),
+ # Line not in macro block
+ (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE-END\nmumble\n',
+ 'Hit a line that wasn\'t a directive and no open macro definition: '),
+ # Redefine macro
+ (u'PDDM-DEFINE foo()\nbody\nPDDM-DEFINE foo(a)\nmumble\n',
+ 'Attempt to redefine macro: '),
+ ]
+ for idx, (input_str, expected_prefix) in enumerate(test_list, 1):
+ f = io.StringIO(input_str)
+ try:
+ result = pddm.MacroCollection(f)
+ self.fail('Should throw exception, entry %d' % idx)
+ except pddm.PDDMError as e:
+ self.assertTrue(e.message.startswith(expected_prefix),
+ 'Entry %d failed: %r' % (idx, e))
+
+ def testParseBeginIssues(self):
+ test_list = [
+ # 1. No name
+ (u'PDDM-DEFINE\nmumble',
+ 'Failed to parse macro definition: '),
+ # 2. No name (with spaces)
+ (u'PDDM-DEFINE \nmumble',
+ 'Failed to parse macro definition: '),
+ # 3. No open paren
+ (u'PDDM-DEFINE foo\nmumble',
+ 'Failed to parse macro definition: '),
+ # 4. No close paren
+ (u'PDDM-DEFINE foo(\nmumble',
+ 'Failed to parse macro definition: '),
+ # 5. No close paren (with args)
+ (u'PDDM-DEFINE foo(a, b\nmumble',
+ 'Failed to parse macro definition: '),
+ # 6. No name before args
+ (u'PDDM-DEFINE (a, b)\nmumble',
+ 'Failed to parse macro definition: '),
+ # 7. No name before args
+ (u'PDDM-DEFINE foo bar(a, b)\nmumble',
+ 'Failed to parse macro definition: '),
+ # 8. Empty arg name
+ (u'PDDM-DEFINE foo(a, ,b)\nmumble',
+ 'Empty arg name in macro definition: '),
+ (u'PDDM-DEFINE foo(a,,b)\nmumble',
+ 'Empty arg name in macro definition: '),
+ # 10. Duplicate name
+ (u'PDDM-DEFINE foo(a,b,a,c)\nmumble',
+ 'Arg name "a" used more than once in macro definition: '),
+ # 11. Invalid arg name
+ (u'PDDM-DEFINE foo(a b,c)\nmumble',
+ 'Invalid arg name "a b" in macro definition: '),
+ (u'PDDM-DEFINE foo(a.b,c)\nmumble',
+ 'Invalid arg name "a.b" in macro definition: '),
+ (u'PDDM-DEFINE foo(a-b,c)\nmumble',
+ 'Invalid arg name "a-b" in macro definition: '),
+ (u'PDDM-DEFINE foo(a,b,c.)\nmumble',
+ 'Invalid arg name "c." in macro definition: '),
+ # 15. Extra stuff after the name
+ (u'PDDM-DEFINE foo(a,c) foo\nmumble',
+ 'Failed to parse macro definition: '),
+ (u'PDDM-DEFINE foo(a,c) foo)\nmumble',
+ 'Failed to parse macro definition: '),
+ ]
+ for idx, (input_str, expected_prefix) in enumerate(test_list, 1):
+ f = io.StringIO(input_str)
+ try:
+ result = pddm.MacroCollection(f)
+ self.fail('Should throw exception, entry %d' % idx)
+ except pddm.PDDMError as e:
+ self.assertTrue(e.message.startswith(expected_prefix),
+ 'Entry %d failed: %r' % (idx, e))
+
+
+class TestExpandingMacros(unittest.TestCase):
+
+ def testExpandBasics(self):
+ f = io.StringIO(u"""
+PDDM-DEFINE noArgs( )
+body1
+body2
+
+PDDM-DEFINE-END
+
+PDDM-DEFINE oneArg(a)
+body3 a
+
+PDDM-DEFINE-END
+
+PDDM-DEFINE twoArgs(b,c)
+body4 b c
+body5
+PDDM-DEFINE-END
+
+""")
+ mc = pddm.MacroCollection(f)
+ test_list = [
+ (u'noArgs()',
+ 'body1\nbody2\n'),
+ (u'oneArg(wee)',
+ 'body3 wee\n'),
+ (u'twoArgs(having some, fun)',
+ 'body4 having some fun\nbody5'),
+ # One arg, pass empty.
+ (u'oneArg()',
+ 'body3 \n'),
+ # Two args, gets empty in each slot.
+ (u'twoArgs(, empty)',
+ 'body4 empty\nbody5'),
+ (u'twoArgs(empty, )',
+ 'body4 empty \nbody5'),
+ (u'twoArgs(, )',
+ 'body4 \nbody5'),
+ ]
+ for idx, (input_str, expected) in enumerate(test_list, 1):
+ result = mc.Expand(input_str)
+ self.assertEqual(result, expected,
+ 'Entry %d --\n Result: %r\n Expected: %r' %
+ (idx, result, expected))
+
+ def testExpandArgOptions(self):
+ f = io.StringIO(u"""
+PDDM-DEFINE bar(a)
+a-a$S-a$l-a$L-a$u-a$U
+PDDM-DEFINE-END
+""")
+ mc = pddm.MacroCollection(f)
+
+ self.assertEqual(mc.Expand('bar(xYz)'), 'xYz- -xYz-xyz-XYz-XYZ')
+ self.assertEqual(mc.Expand('bar(MnoP)'), 'MnoP- -mnoP-mnop-MnoP-MNOP')
+ # Test empty
+ self.assertEqual(mc.Expand('bar()'), '-----')
+
+ def testExpandSimpleMacroErrors(self):
+ f = io.StringIO(u"""
+PDDM-DEFINE foo(a, b)
+<a-z>
+PDDM-DEFINE baz(a)
+a - a$z
+""")
+ mc = pddm.MacroCollection(f)
+ test_list = [
+ # 1. Unknown macro
+ (u'bar()',
+ 'No macro named "bar".'),
+ (u'bar(a)',
+ 'No macro named "bar".'),
+ # 3. Arg mismatch
+ (u'foo()',
+ 'Expected 2 args, got: "foo()".'),
+ (u'foo(a b)',
+ 'Expected 2 args, got: "foo(a b)".'),
+ (u'foo(a,b,c)',
+ 'Expected 2 args, got: "foo(a,b,c)".'),
+ # 6. Unknown option in expansion
+ (u'baz(mumble)',
+ 'Unknown arg option "a$z" while expanding "baz(mumble)".'),
+ ]
+ for idx, (input_str, expected_err) in enumerate(test_list, 1):
+ try:
+ result = mc.Expand(input_str)
+ self.fail('Should throw exception, entry %d' % idx)
+ except pddm.PDDMError as e:
+ self.assertEqual(e.message, expected_err,
+ 'Entry %d failed: %r' % (idx, e))
+
+ def testExpandReferences(self):
+ f = io.StringIO(u"""
+PDDM-DEFINE StartIt()
+foo(abc, def)
+foo(ghi, jkl)
+PDDM-DEFINE foo(a, b)
+bar(a, int)
+bar(b, NSString *)
+PDDM-DEFINE bar(n, t)
+- (t)n;
+- (void)set##n$u##:(t)value;
+
+""")
+ mc = pddm.MacroCollection(f)
+ expected = """- (int)abc;
+- (void)setAbc:(int)value;
+
+- (NSString *)def;
+- (void)setDef:(NSString *)value;
+
+- (int)ghi;
+- (void)setGhi:(int)value;
+
+- (NSString *)jkl;
+- (void)setJkl:(NSString *)value;
+"""
+ self.assertEqual(mc.Expand('StartIt()'), expected)
+
+ def testCatchRecursion(self):
+ f = io.StringIO(u"""
+PDDM-DEFINE foo(a, b)
+bar(1, a)
+bar(2, b)
+PDDM-DEFINE bar(x, y)
+foo(x, y)
+""")
+ mc = pddm.MacroCollection(f)
+ try:
+ result = mc.Expand('foo(A,B)')
+ self.fail('Should throw exception, entry %d' % idx)
+ except pddm.PDDMError as e:
+ self.assertEqual(e.message,
+ 'Found macro recusion, invoking "foo(1, A)":\n...while expanding "bar(1, A)".\n...while expanding "foo(A,B)".')
+
+
+class TestParsingSource(unittest.TestCase):
+
+ def testBasicParse(self):
+ test_list = [
+ # 1. no directives
+ (u'a\nb\nc',
+ (3,) ),
+ # 2. One define
+ (u'a\n//%PDDM-DEFINE foo()\n//%body\nc',
+ (1, 2, 1) ),
+ # 3. Two defines
+ (u'a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE bar()\n//%body2\nc',
+ (1, 4, 1) ),
+ # 4. Two defines with ends
+ (u'a\n//%PDDM-DEFINE foo()\n//%body\n//%PDDM-DEFINE-END\n'
+ u'//%PDDM-DEFINE bar()\n//%body2\n//%PDDM-DEFINE-END\nc',
+ (1, 6, 1) ),
+ # 5. One expand, one define (that runs to end of file)
+ (u'a\n//%PDDM-EXPAND foo()\nbody\n//%PDDM-EXPAND-END\n'
+ u'//%PDDM-DEFINE bar()\n//%body2\n',
+ (1, 1, 2) ),
+ # 6. One define ended with an expand.
+ (u'a\nb\n//%PDDM-DEFINE bar()\n//%body2\n'
+ u'//%PDDM-EXPAND bar()\nbody2\n//%PDDM-EXPAND-END\n',
+ (2, 2, 1) ),
+ # 7. Two expands (one end), one define.
+ (u'a\n//%PDDM-EXPAND foo(1)\nbody\n//%PDDM-EXPAND foo(2)\nbody2\n//%PDDM-EXPAND-END\n'
+ u'//%PDDM-DEFINE foo()\n//%body2\n',
+ (1, 2, 2) ),
+ ]
+ for idx, (input_str, line_counts) in enumerate(test_list, 1):
+ f = io.StringIO(input_str)
+ sf = pddm.SourceFile(f)
+ sf._ParseFile()
+ self.assertEqual(len(sf._sections), len(line_counts),
+ 'Entry %d -- %d != %d' %
+ (idx, len(sf._sections), len(line_counts)))
+ for idx2, (sec, expected) in enumerate(zip(sf._sections, line_counts), 1):
+ self.assertEqual(sec.num_lines_captured, expected,
+ 'Entry %d, section %d -- %d != %d' %
+ (idx, idx2, sec.num_lines_captured, expected))
+
+ def testErrors(self):
+ test_list = [
+ # 1. Directive within expansion
+ (u'//%PDDM-EXPAND a()\n//%PDDM-BOGUS',
+ 'Ran into directive ("//%PDDM-BOGUS", line 2) while in "//%PDDM-EXPAND a()".'),
+ (u'//%PDDM-EXPAND a()\n//%PDDM-DEFINE a()\n//%body\n',
+ 'Ran into directive ("//%PDDM-DEFINE", line 2) while in "//%PDDM-EXPAND a()".'),
+ # 3. Expansion ran off end of file
+ (u'//%PDDM-EXPAND a()\na\nb\n',
+ 'Hit the end of the file while in "//%PDDM-EXPAND a()".'),
+ # 4. Directive within define
+ (u'//%PDDM-DEFINE a()\n//%body\n//%PDDM-BOGUS',
+ 'Ran into directive ("//%PDDM-BOGUS", line 3) while in "//%PDDM-DEFINE a()".'),
+ (u'//%PDDM-DEFINE a()\n//%body\n//%PDDM-EXPAND-END a()',
+ 'Ran into directive ("//%PDDM-EXPAND-END", line 3) while in "//%PDDM-DEFINE a()".'),
+ # 6. Directives that shouldn't start sections
+ (u'a\n//%PDDM-DEFINE-END a()\n//a\n',
+ 'Unexpected line 2: "//%PDDM-DEFINE-END a()".'),
+ (u'a\n//%PDDM-EXPAND-END a()\n//a\n',
+ 'Unexpected line 2: "//%PDDM-EXPAND-END a()".'),
+ (u'//%PDDM-BOGUS\n//a\n',
+ 'Unexpected line 1: "//%PDDM-BOGUS".'),
+ ]
+ for idx, (input_str, expected_err) in enumerate(test_list, 1):
+ f = io.StringIO(input_str)
+ try:
+ pddm.SourceFile(f)._ParseFile()
+ self.fail('Should throw exception, entry %d' % idx)
+ except pddm.PDDMError as e:
+ self.assertEqual(e.message, expected_err,
+ 'Entry %d failed: %r' % (idx, e))
+
+class TestProcessingSource(unittest.TestCase):
+
+ def testBasics(self):
+ input_str = u"""
+//%PDDM-IMPORT-DEFINES ImportFile
+foo
+//%PDDM-EXPAND mumble(abc)
+//%PDDM-EXPAND-END
+bar
+//%PDDM-EXPAND mumble(def)
+//%PDDM-EXPAND mumble(ghi)
+//%PDDM-EXPAND-END
+baz
+//%PDDM-DEFINE mumble(a_)
+//%a_: getName(a_)
+"""
+ input_str2 = u"""
+//%PDDM-DEFINE getName(x_)
+//%do##x_$u##(int x_);
+
+"""
+ expected = u"""
+//%PDDM-IMPORT-DEFINES ImportFile
+foo
+//%PDDM-EXPAND mumble(abc)
+// This block of code is generated, do not edit it directly.
+
+abc: doAbc(int abc);
+//%PDDM-EXPAND-END mumble(abc)
+bar
+//%PDDM-EXPAND mumble(def)
+// This block of code is generated, do not edit it directly.
+
+def: doDef(int def);
+//%PDDM-EXPAND mumble(ghi)
+// This block of code is generated, do not edit it directly.
+
+ghi: doGhi(int ghi);
+//%PDDM-EXPAND-END (2 expansions)
+baz
+//%PDDM-DEFINE mumble(a_)
+//%a_: getName(a_)
+"""
+ expected_stripped = u"""
+//%PDDM-IMPORT-DEFINES ImportFile
+foo
+//%PDDM-EXPAND mumble(abc)
+//%PDDM-EXPAND-END mumble(abc)
+bar
+//%PDDM-EXPAND mumble(def)
+//%PDDM-EXPAND mumble(ghi)
+//%PDDM-EXPAND-END (2 expansions)
+baz
+//%PDDM-DEFINE mumble(a_)
+//%a_: getName(a_)
+"""
+ def _Resolver(name):
+ self.assertEqual(name, 'ImportFile')
+ return io.StringIO(input_str2)
+ f = io.StringIO(input_str)
+ sf = pddm.SourceFile(f, _Resolver)
+ sf.ProcessContent()
+ self.assertEqual(sf.processed_content, expected)
+ # Feed it through and nothing should change.
+ f2 = io.StringIO(sf.processed_content)
+ sf2 = pddm.SourceFile(f2, _Resolver)
+ sf2.ProcessContent()
+ self.assertEqual(sf2.processed_content, expected)
+ self.assertEqual(sf2.processed_content, sf.processed_content)
+ # Test stripping (with the original input and expanded version).
+ f2 = io.StringIO(input_str)
+ sf2 = pddm.SourceFile(f2)
+ sf2.ProcessContent(strip_expansion=True)
+ self.assertEqual(sf2.processed_content, expected_stripped)
+ f2 = io.StringIO(sf.processed_content)
+ sf2 = pddm.SourceFile(f2, _Resolver)
+ sf2.ProcessContent(strip_expansion=True)
+ self.assertEqual(sf2.processed_content, expected_stripped)
+
+ def testProcessFileWithMacroParseError(self):
+ input_str = u"""
+foo
+//%PDDM-DEFINE mumble(a_)
+//%body
+//%PDDM-DEFINE mumble(x_)
+//%body2
+
+"""
+ f = io.StringIO(input_str)
+ sf = pddm.SourceFile(f)
+ try:
+ sf.ProcessContent()
+ self.fail('Should throw exception, entry %d' % idx)
+ except pddm.PDDMError as e:
+ self.assertEqual(e.message,
+ 'Attempt to redefine macro: "PDDM-DEFINE mumble(x_)"\n'
+ '...while parsing section that started:\n'
+ ' Line 3: //%PDDM-DEFINE mumble(a_)')
+
+ def testProcessFileWithExpandError(self):
+ input_str = u"""
+foo
+//%PDDM-DEFINE mumble(a_)
+//%body
+//%PDDM-EXPAND foobar(x_)
+//%PDDM-EXPAND-END
+
+"""
+ f = io.StringIO(input_str)
+ sf = pddm.SourceFile(f)
+ try:
+ sf.ProcessContent()
+ self.fail('Should throw exception, entry %d' % idx)
+ except pddm.PDDMError as e:
+ self.assertEqual(e.message,
+ 'No macro named "foobar".\n'
+ '...while expanding "foobar(x_)" from the section that'
+ ' started:\n Line 5: //%PDDM-EXPAND foobar(x_)')
+
+
+if __name__ == '__main__':
+ unittest.main()
diff --git a/objectivec/GPBArray.h b/objectivec/GPBArray.h
new file mode 100644
index 00000000..3fcba7af
--- /dev/null
+++ b/objectivec/GPBArray.h
@@ -0,0 +1,535 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBTypes.h"
+
+// These classes are used for repeated fields of basic data types. They are used because
+// they perform better than boxing into NSNumbers in NSArrays.
+
+// Note: These are not meant to be subclassed.
+
+//%PDDM-EXPAND DECLARE_ARRAYS()
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32
+
+@interface GPBInt32Array : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(int32_t)value;
++ (instancetype)arrayWithValueArray:(GPBInt32Array *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const int32_t [])values
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithValueArray:(GPBInt32Array *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (int32_t)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(int32_t)value;
+- (void)addValues:(const int32_t [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBInt32Array *)array;
+
+- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - UInt32
+
+@interface GPBUInt32Array : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(uint32_t)value;
++ (instancetype)arrayWithValueArray:(GPBUInt32Array *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const uint32_t [])values
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithValueArray:(GPBUInt32Array *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (uint32_t)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(uint32_t)value;
+- (void)addValues:(const uint32_t [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBUInt32Array *)array;
+
+- (void)insertValue:(uint32_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint32_t)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - Int64
+
+@interface GPBInt64Array : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(int64_t)value;
++ (instancetype)arrayWithValueArray:(GPBInt64Array *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const int64_t [])values
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithValueArray:(GPBInt64Array *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (int64_t)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(int64_t)value;
+- (void)addValues:(const int64_t [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBInt64Array *)array;
+
+- (void)insertValue:(int64_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int64_t)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - UInt64
+
+@interface GPBUInt64Array : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(uint64_t)value;
++ (instancetype)arrayWithValueArray:(GPBUInt64Array *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const uint64_t [])values
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithValueArray:(GPBUInt64Array *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (uint64_t)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(uint64_t)value;
+- (void)addValues:(const uint64_t [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBUInt64Array *)array;
+
+- (void)insertValue:(uint64_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint64_t)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - Float
+
+@interface GPBFloatArray : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(float)value;
++ (instancetype)arrayWithValueArray:(GPBFloatArray *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const float [])values
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithValueArray:(GPBFloatArray *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (float)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(float)value;
+- (void)addValues:(const float [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBFloatArray *)array;
+
+- (void)insertValue:(float)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(float)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - Double
+
+@interface GPBDoubleArray : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(double)value;
++ (instancetype)arrayWithValueArray:(GPBDoubleArray *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const double [])values
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithValueArray:(GPBDoubleArray *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (double)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(double)value;
+- (void)addValues:(const double [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBDoubleArray *)array;
+
+- (void)insertValue:(double)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(double)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - Bool
+
+@interface GPBBoolArray : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)array;
++ (instancetype)arrayWithValue:(BOOL)value;
++ (instancetype)arrayWithValueArray:(GPBBoolArray *)array;
++ (instancetype)arrayWithCapacity:(NSUInteger)count;
+
+// Initializes the array, copying the values.
+- (instancetype)initWithValues:(const BOOL [])values
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithValueArray:(GPBBoolArray *)array;
+- (instancetype)initWithCapacity:(NSUInteger)count;
+
+- (BOOL)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block;
+
+- (void)addValue:(BOOL)value;
+- (void)addValues:(const BOOL [])values count:(NSUInteger)count;
+- (void)addValuesFromArray:(GPBBoolArray *)array;
+
+- (void)insertValue:(BOOL)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(BOOL)value;
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+#pragma mark - Enum
+
+@interface GPBEnumArray : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)array;
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func;
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)value;
++ (instancetype)arrayWithValueArray:(GPBEnumArray *)array;
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)count;
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func;
+
+// Initializes the array, copying the values.
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithValueArray:(GPBEnumArray *)array;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)count;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value at index is not a
+// valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (int32_t)valueAtIndex:(NSUInteger)index;
+
+- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (int32_t)rawValueAtIndex:(NSUInteger)index;
+
+- (void)enumerateRawValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)addValue:(int32_t)value;
+- (void)addValues:(const int32_t [])values count:(NSUInteger)count;
+
+- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value;
+
+// These methods bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+
+- (void)addRawValue:(int32_t)value;
+- (void)addRawValuesFromArray:(GPBEnumArray *)array;
+- (void)addRawValues:(const int32_t [])values count:(NSUInteger)count;
+
+- (void)insertRawValue:(int32_t)value atIndex:(NSUInteger)index;
+
+- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(int32_t)value;
+
+// No validation applies to these methods.
+
+- (void)removeValueAtIndex:(NSUInteger)index;
+- (void)removeAll;
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2;
+
+@end
+
+//%PDDM-EXPAND-END DECLARE_ARRAYS()
+
+//%PDDM-DEFINE DECLARE_ARRAYS()
+//%ARRAY_INTERFACE_SIMPLE(Int32, int32_t)
+//%ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t)
+//%ARRAY_INTERFACE_SIMPLE(Int64, int64_t)
+//%ARRAY_INTERFACE_SIMPLE(UInt64, uint64_t)
+//%ARRAY_INTERFACE_SIMPLE(Float, float)
+//%ARRAY_INTERFACE_SIMPLE(Double, double)
+//%ARRAY_INTERFACE_SIMPLE(Bool, BOOL)
+//%ARRAY_INTERFACE_ENUM(Enum, int32_t)
+
+//
+// The common case (everything but Enum)
+//
+
+//%PDDM-DEFINE ARRAY_INTERFACE_SIMPLE(NAME, TYPE)
+//%#pragma mark - NAME
+//%
+//%@interface GPB##NAME##Array : NSObject <NSCopying>
+//%
+//%@property(nonatomic, readonly) NSUInteger count;
+//%
+//%+ (instancetype)array;
+//%+ (instancetype)arrayWithValue:(TYPE)value;
+//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array;
+//%+ (instancetype)arrayWithCapacity:(NSUInteger)count;
+//%
+//%// Initializes the array, copying the values.
+//%- (instancetype)initWithValues:(const TYPE [])values
+//% count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array;
+//%- (instancetype)initWithCapacity:(NSUInteger)count;
+//%
+//%ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, Basic)
+//%
+//%ARRAY_MUTABLE_INTERFACE(NAME, TYPE, Basic)
+//%
+//%@end
+//%
+
+//
+// Macros specific to Enums (to tweak their interface).
+//
+
+//%PDDM-DEFINE ARRAY_INTERFACE_ENUM(NAME, TYPE)
+//%#pragma mark - NAME
+//%
+//%@interface GPB##NAME##Array : NSObject <NSCopying>
+//%
+//%@property(nonatomic, readonly) NSUInteger count;
+//%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+//%
+//%+ (instancetype)array;
+//%+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func;
+//%+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func
+//% rawValue:(TYPE)value;
+//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array;
+//%+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func
+//% capacity:(NSUInteger)count;
+//%
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func;
+//%
+//%// Initializes the array, copying the values.
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+//% rawValues:(const TYPE [])values
+//% count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array;
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+//% capacity:(NSUInteger)count;
+//%
+//%// These will return kGPBUnrecognizedEnumeratorValue if the value at index is not a
+//%// valid enumerator as defined by validationFunc. If the actual value is
+//%// desired, use "raw" version of the method.
+//%
+//%ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, NAME)
+//%
+//%// These methods bypass the validationFunc to provide access to values that were not
+//%// known at the time the binary was compiled.
+//%
+//%- (TYPE)rawValueAtIndex:(NSUInteger)index;
+//%
+//%- (void)enumerateRawValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
+//% usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%
+//%// If value is not a valid enumerator as defined by validationFunc, these
+//%// methods will assert in debug, and will log in release and assign the value
+//%// to the default value. Use the rawValue methods below to assign non enumerator
+//%// values.
+//%
+//%ARRAY_MUTABLE_INTERFACE(NAME, TYPE, NAME)
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE ARRAY_IMMUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME)
+//%- (TYPE)valueAtIndex:(NSUInteger)index;
+//%
+//%- (void)enumerateValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+//% usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+
+//%PDDM-DEFINE ARRAY_MUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME)
+//%- (void)addValue:(TYPE)value;
+//%- (void)addValues:(const TYPE [])values count:(NSUInteger)count;
+//%ARRAY_EXTRA_MUTABLE_METHODS1_##HELPER_NAME(NAME, TYPE)
+//%- (void)insertValue:(TYPE)value atIndex:(NSUInteger)index;
+//%
+//%- (void)replaceValueAtIndex:(NSUInteger)index withValue:(TYPE)value;
+//%ARRAY_EXTRA_MUTABLE_METHODS2_##HELPER_NAME(NAME, TYPE)
+//%- (void)removeValueAtIndex:(NSUInteger)index;
+//%- (void)removeAll;
+//%
+//%- (void)exchangeValueAtIndex:(NSUInteger)idx1
+//% withValueAtIndex:(NSUInteger)idx2;
+
+//
+// These are hooks invoked by the above to do insert as needed.
+//
+
+//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS1_Basic(NAME, TYPE)
+//%- (void)addValuesFromArray:(GPB##NAME##Array *)array;
+//%
+//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS2_Basic(NAME, TYPE)
+// Empty
+//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS1_Enum(NAME, TYPE)
+// Empty
+//%PDDM-DEFINE ARRAY_EXTRA_MUTABLE_METHODS2_Enum(NAME, TYPE)
+//%
+//%// These methods bypass the validationFunc to provide setting of values that were not
+//%// known at the time the binary was compiled.
+//%
+//%- (void)addRawValue:(TYPE)value;
+//%- (void)addRawValuesFromArray:(GPB##NAME##Array *)array;
+//%- (void)addRawValues:(const TYPE [])values count:(NSUInteger)count;
+//%
+//%- (void)insertRawValue:(TYPE)value atIndex:(NSUInteger)index;
+//%
+//%- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(TYPE)value;
+//%
+//%// No validation applies to these methods.
+//%
diff --git a/objectivec/GPBArray.m b/objectivec/GPBArray.m
new file mode 100644
index 00000000..6aa3df2e
--- /dev/null
+++ b/objectivec/GPBArray.m
@@ -0,0 +1,2499 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBArray_PackagePrivate.h"
+
+#import "GPBMessage_PackagePrivate.h"
+
+// Mutable arrays use an internal buffer that can always hold a multiple of this elements.
+#define kChunkSize 16
+#define CapacityFromCount(x) (((x / kChunkSize) + 1) * kChunkSize)
+
+static BOOL ArrayDefault_IsValidValue(int32_t value) {
+ // Anything but the bad value marker is allowed.
+ return (value != kGPBUnrecognizedEnumeratorValue);
+}
+
+//%PDDM-DEFINE VALIDATE_RANGE(INDEX, COUNT)
+//% if (INDEX >= COUNT) {
+//% [NSException raise:NSRangeException
+//% format:@"Index (%lu) beyond bounds (%lu)",
+//% (unsigned long)INDEX, (unsigned long)COUNT];
+//% }
+//%PDDM-DEFINE MAYBE_GROW_TO_SET_COUNT(NEW_COUNT)
+//% if (NEW_COUNT > _capacity) {
+//% [self internalResizeToCapacity:CapacityFromCount(NEW_COUNT)];
+//% }
+//% _count = NEW_COUNT;
+//%PDDM-DEFINE SET_COUNT_AND_MAYBE_SHRINK(NEW_COUNT)
+//% _count = NEW_COUNT;
+//% if ((NEW_COUNT + (2 * kChunkSize)) < _capacity) {
+//% [self internalResizeToCapacity:CapacityFromCount(NEW_COUNT)];
+//% }
+
+//
+// Macros for the common basic cases.
+//
+
+//%PDDM-DEFINE ARRAY_INTERFACE_SIMPLE(NAME, TYPE, FORMAT)
+//%#pragma mark - NAME
+//%
+//%@implementation GPB##NAME##Array {
+//% @package
+//% TYPE *_values;
+//% NSUInteger _count;
+//% NSUInteger _capacity;
+//%}
+//%
+//%@synthesize count = _count;
+//%
+//%+ (instancetype)array {
+//% return [[[self alloc] initWithValues:NULL count:0] autorelease];
+//%}
+//%
+//%+ (instancetype)arrayWithValue:(TYPE)value {
+//% // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+//% // the type correct.
+//% return [[(GPB##NAME##Array*)[self alloc] initWithValues:&value count:1] autorelease];
+//%}
+//%
+//%+ (instancetype)arrayWithValueArray:(GPB##NAME##Array *)array {
+//% return [[(GPB##NAME##Array*)[self alloc] initWithValueArray:array] autorelease];
+//%}
+//%
+//%+ (instancetype)arrayWithCapacity:(NSUInteger)count {
+//% return [[[self alloc] initWithCapacity:count] autorelease];
+//%}
+//%
+//%- (instancetype)init {
+//% return [self initWithValues:NULL count:0];
+//%}
+//%
+//%- (instancetype)initWithValueArray:(GPB##NAME##Array *)array {
+//% return [self initWithValues:array->_values count:array->_count];
+//%}
+//%
+//%- (instancetype)initWithValues:(const TYPE [])values count:(NSUInteger)count {
+//% self = [super init];
+//% if (self) {
+//% if (count && values) {
+//% _values = malloc(count * sizeof(TYPE));
+//% if (values != NULL) {
+//% _capacity = count;
+//% memcpy(_values, values, count * sizeof(TYPE));
+//% _count = count;
+//% } else {
+//% [self release];
+//% [NSException raise:NSMallocException
+//% format:@"Failed to allocate %lu bytes",
+//% (unsigned long)(count * sizeof(TYPE))];
+//% }
+//% }
+//% }
+//% return self;
+//%}
+//%
+//%- (instancetype)initWithCapacity:(NSUInteger)count {
+//% self = [self initWithValues:NULL count:0];
+//% if (self && count) {
+//% [self internalResizeToCapacity:count];
+//% }
+//% return self;
+//%}
+//%
+//%- (instancetype)copyWithZone:(NSZone *)zone {
+//% return [[GPB##NAME##Array allocWithZone:zone] initWithValues:_values count:_count];
+//%}
+//%
+//%ARRAY_IMMUTABLE_CORE(NAME, TYPE, , FORMAT)
+//%
+//%- (TYPE)valueAtIndex:(NSUInteger)index {
+//%VALIDATE_RANGE(index, _count)
+//% return _values[index];
+//%}
+//%
+//%ARRAY_MUTABLE_CORE(NAME, TYPE, , FORMAT)
+//%@end
+//%
+
+//
+// Some core macros used for both the simple types and Enums.
+//
+
+//%PDDM-DEFINE ARRAY_IMMUTABLE_CORE(NAME, TYPE, ACCESSOR_NAME, FORMAT)
+//%- (void)dealloc {
+//% NSAssert(!_autocreator, @"Autocreator must be cleared before release.");
+//% free(_values);
+//% [super dealloc];
+//%}
+//%
+//%- (BOOL)isEqual:(GPB##NAME##Array *)other {
+//% if (self == other) {
+//% return YES;
+//% }
+//% if (![other isKindOfClass:[GPB##NAME##Array class]]) {
+//% return NO;
+//% }
+//% return (_count == other->_count
+//% && memcmp(_values, other->_values, (_count * sizeof(TYPE))) == 0);
+//%}
+//%
+//%- (NSUInteger)hash {
+//% // Follow NSArray's lead, and use the count as the hash.
+//% return _count;
+//%}
+//%
+//%- (NSString *)description {
+//% NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+//% for (NSUInteger i = 0, count = _count; i < count; ++i) {
+//% if (i == 0) {
+//% [result appendFormat:@"##FORMAT##", _values[i]];
+//% } else {
+//% [result appendFormat:@", ##FORMAT##", _values[i]];
+//% }
+//% }
+//% [result appendFormat:@" }"];
+//% return result;
+//%}
+//%
+//%- (void)enumerate##ACCESSOR_NAME##ValuesWithBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block {
+//% [self enumerate##ACCESSOR_NAME##ValuesWithOptions:0 usingBlock:block];
+//%}
+//%
+//%- (void)enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)opts
+//% ACCESSOR_NAME$S usingBlock:(void (^)(TYPE value, NSUInteger idx, BOOL *stop))block {
+//% // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+//% BOOL stop = NO;
+//% if ((opts & NSEnumerationReverse) == 0) {
+//% for (NSUInteger i = 0, count = _count; i < count; ++i) {
+//% block(_values[i], i, &stop);
+//% if (stop) break;
+//% }
+//% } else if (_count > 0) {
+//% for (NSUInteger i = _count; i > 0; --i) {
+//% block(_values[i - 1], (i - 1), &stop);
+//% if (stop) break;
+//% }
+//% }
+//%}
+
+//%PDDM-DEFINE MUTATION_HOOK_None()
+//%PDDM-DEFINE MUTATION_METHODS(NAME, TYPE, ACCESSOR_NAME, HOOK_1, HOOK_2)
+//%- (void)add##ACCESSOR_NAME##Value:(TYPE)value {
+//% [self add##ACCESSOR_NAME##Values:&value count:1];
+//%}
+//%
+//%- (void)add##ACCESSOR_NAME##Values:(const TYPE [])values count:(NSUInteger)count {
+//% if (values == NULL || count == 0) return;
+//%MUTATION_HOOK_##HOOK_1() NSUInteger initialCount = _count;
+//% NSUInteger newCount = initialCount + count;
+//%MAYBE_GROW_TO_SET_COUNT(newCount);
+//% memcpy(&_values[initialCount], values, count * sizeof(TYPE));
+//% if (_autocreator) {
+//% GPBAutocreatedArrayModified(_autocreator, self);
+//% }
+//%}
+//%
+//%- (void)insert##ACCESSOR_NAME##Value:(TYPE)value atIndex:(NSUInteger)index {
+//%VALIDATE_RANGE(index, _count + 1)
+//%MUTATION_HOOK_##HOOK_2() NSUInteger initialCount = _count;
+//% NSUInteger newCount = initialCount + 1;
+//%MAYBE_GROW_TO_SET_COUNT(newCount);
+//% if (index != initialCount) {
+//% memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(TYPE));
+//% }
+//% _values[index] = value;
+//% if (_autocreator) {
+//% GPBAutocreatedArrayModified(_autocreator, self);
+//% }
+//%}
+//%
+//%- (void)replaceValueAtIndex:(NSUInteger)index with##ACCESSOR_NAME##Value:(TYPE)value {
+//%VALIDATE_RANGE(index, _count)
+//%MUTATION_HOOK_##HOOK_2() _values[index] = value;
+//%}
+
+//%PDDM-DEFINE ARRAY_MUTABLE_CORE(NAME, TYPE, ACCESSOR_NAME, FORMAT)
+//%- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+//% _values = reallocf(_values, newCapacity * sizeof(TYPE));
+//% if (_values == NULL) {
+//% _capacity = 0;
+//% _count = 0;
+//% [NSException raise:NSMallocException
+//% format:@"Failed to allocate %lu bytes",
+//% (unsigned long)(newCapacity * sizeof(TYPE))];
+//% }
+//% _capacity = newCapacity;
+//%}
+//%
+//%MUTATION_METHODS(NAME, TYPE, ACCESSOR_NAME, None, None)
+//%
+//%- (void)add##ACCESSOR_NAME##ValuesFromArray:(GPB##NAME##Array *)array {
+//% [self add##ACCESSOR_NAME##Values:array->_values count:array->_count];
+//%}
+//%
+//%- (void)removeValueAtIndex:(NSUInteger)index {
+//%VALIDATE_RANGE(index, _count)
+//% NSUInteger newCount = _count - 1;
+//% if (index != newCount) {
+//% memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(TYPE));
+//% }
+//%SET_COUNT_AND_MAYBE_SHRINK(newCount)
+//%}
+//%
+//%- (void)removeAll {
+//%SET_COUNT_AND_MAYBE_SHRINK(0)
+//%}
+//%
+//%- (void)exchangeValueAtIndex:(NSUInteger)idx1
+//% withValueAtIndex:(NSUInteger)idx2 {
+//%VALIDATE_RANGE(idx1, _count)
+//%VALIDATE_RANGE(idx2, _count)
+//% TYPE temp = _values[idx1];
+//% _values[idx1] = _values[idx2];
+//% _values[idx2] = temp;
+//%}
+//%
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int32, int32_t, %d)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32
+
+@implementation GPBInt32Array {
+ @package
+ int32_t *_values;
+ NSUInteger _count;
+ NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+ return [[[self alloc] initWithValues:NULL count:0] autorelease];
+}
+
++ (instancetype)arrayWithValue:(int32_t)value {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+ // the type correct.
+ return [[(GPBInt32Array*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBInt32Array *)array {
+ return [[(GPBInt32Array*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+ return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL count:0];
+}
+
+- (instancetype)initWithValueArray:(GPBInt32Array *)array {
+ return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ if (count && values) {
+ _values = malloc(count * sizeof(int32_t));
+ if (values != NULL) {
+ _capacity = count;
+ memcpy(_values, values, count * sizeof(int32_t));
+ _count = count;
+ } else {
+ [self release];
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(count * sizeof(int32_t))];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+ self = [self initWithValues:NULL count:0];
+ if (self && count) {
+ [self internalResizeToCapacity:count];
+ }
+ return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt32Array allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+ NSAssert(!_autocreator, @"Autocreator must be cleared before release.");
+ free(_values);
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBInt32Array *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt32Array class]]) {
+ return NO;
+ }
+ return (_count == other->_count
+ && memcmp(_values, other->_values, (_count * sizeof(int32_t))) == 0);
+}
+
+- (NSUInteger)hash {
+ // Follow NSArray's lead, and use the count as the hash.
+ return _count;
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ if (i == 0) {
+ [result appendFormat:@"%d", _values[i]];
+ } else {
+ [result appendFormat:@", %d", _values[i]];
+ }
+ }
+ [result appendFormat:@" }"];
+ return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+ [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+ // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+ BOOL stop = NO;
+ if ((opts & NSEnumerationReverse) == 0) {
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ block(_values[i], i, &stop);
+ if (stop) break;
+ }
+ } else if (_count > 0) {
+ for (NSUInteger i = _count; i > 0; --i) {
+ block(_values[i - 1], (i - 1), &stop);
+ if (stop) break;
+ }
+ }
+}
+
+- (int32_t)valueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+ _values = reallocf(_values, newCapacity * sizeof(int32_t));
+ if (_values == NULL) {
+ _capacity = 0;
+ _count = 0;
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(newCapacity * sizeof(int32_t))];
+ }
+ _capacity = newCapacity;
+}
+
+- (void)addValue:(int32_t)value {
+ [self addValues:&value count:1];
+}
+
+- (void)addValues:(const int32_t [])values count:(NSUInteger)count {
+ if (values == NULL || count == 0) return;
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + count;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ memcpy(&_values[initialCount], values, count * sizeof(int32_t));
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index {
+ if (index >= _count + 1) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count + 1];
+ }
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + 1;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ if (index != initialCount) {
+ memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t));
+ }
+ _values[index] = value;
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBInt32Array *)array {
+ [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ NSUInteger newCount = _count - 1;
+ if (index != newCount) {
+ memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int32_t));
+ }
+ _count = newCount;
+ if ((newCount + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+}
+
+- (void)removeAll {
+ _count = 0;
+ if ((0 + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(0)];
+ }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2 {
+ if (idx1 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx1, (unsigned long)_count];
+ }
+ if (idx2 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx2, (unsigned long)_count];
+ }
+ int32_t temp = _values[idx1];
+ _values[idx1] = _values[idx2];
+ _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t, %u)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt32
+
+@implementation GPBUInt32Array {
+ @package
+ uint32_t *_values;
+ NSUInteger _count;
+ NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+ return [[[self alloc] initWithValues:NULL count:0] autorelease];
+}
+
++ (instancetype)arrayWithValue:(uint32_t)value {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+ // the type correct.
+ return [[(GPBUInt32Array*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBUInt32Array *)array {
+ return [[(GPBUInt32Array*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+ return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL count:0];
+}
+
+- (instancetype)initWithValueArray:(GPBUInt32Array *)array {
+ return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ if (count && values) {
+ _values = malloc(count * sizeof(uint32_t));
+ if (values != NULL) {
+ _capacity = count;
+ memcpy(_values, values, count * sizeof(uint32_t));
+ _count = count;
+ } else {
+ [self release];
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(count * sizeof(uint32_t))];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+ self = [self initWithValues:NULL count:0];
+ if (self && count) {
+ [self internalResizeToCapacity:count];
+ }
+ return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt32Array allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+ NSAssert(!_autocreator, @"Autocreator must be cleared before release.");
+ free(_values);
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBUInt32Array *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt32Array class]]) {
+ return NO;
+ }
+ return (_count == other->_count
+ && memcmp(_values, other->_values, (_count * sizeof(uint32_t))) == 0);
+}
+
+- (NSUInteger)hash {
+ // Follow NSArray's lead, and use the count as the hash.
+ return _count;
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ if (i == 0) {
+ [result appendFormat:@"%u", _values[i]];
+ } else {
+ [result appendFormat:@", %u", _values[i]];
+ }
+ }
+ [result appendFormat:@" }"];
+ return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block {
+ [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(uint32_t value, NSUInteger idx, BOOL *stop))block {
+ // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+ BOOL stop = NO;
+ if ((opts & NSEnumerationReverse) == 0) {
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ block(_values[i], i, &stop);
+ if (stop) break;
+ }
+ } else if (_count > 0) {
+ for (NSUInteger i = _count; i > 0; --i) {
+ block(_values[i - 1], (i - 1), &stop);
+ if (stop) break;
+ }
+ }
+}
+
+- (uint32_t)valueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+ _values = reallocf(_values, newCapacity * sizeof(uint32_t));
+ if (_values == NULL) {
+ _capacity = 0;
+ _count = 0;
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(newCapacity * sizeof(uint32_t))];
+ }
+ _capacity = newCapacity;
+}
+
+- (void)addValue:(uint32_t)value {
+ [self addValues:&value count:1];
+}
+
+- (void)addValues:(const uint32_t [])values count:(NSUInteger)count {
+ if (values == NULL || count == 0) return;
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + count;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ memcpy(&_values[initialCount], values, count * sizeof(uint32_t));
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)insertValue:(uint32_t)value atIndex:(NSUInteger)index {
+ if (index >= _count + 1) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count + 1];
+ }
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + 1;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ if (index != initialCount) {
+ memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(uint32_t));
+ }
+ _values[index] = value;
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint32_t)value {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBUInt32Array *)array {
+ [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ NSUInteger newCount = _count - 1;
+ if (index != newCount) {
+ memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(uint32_t));
+ }
+ _count = newCount;
+ if ((newCount + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+}
+
+- (void)removeAll {
+ _count = 0;
+ if ((0 + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(0)];
+ }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2 {
+ if (idx1 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx1, (unsigned long)_count];
+ }
+ if (idx2 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx2, (unsigned long)_count];
+ }
+ uint32_t temp = _values[idx1];
+ _values[idx1] = _values[idx2];
+ _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int64, int64_t, %lld)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int64
+
+@implementation GPBInt64Array {
+ @package
+ int64_t *_values;
+ NSUInteger _count;
+ NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+ return [[[self alloc] initWithValues:NULL count:0] autorelease];
+}
+
++ (instancetype)arrayWithValue:(int64_t)value {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+ // the type correct.
+ return [[(GPBInt64Array*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBInt64Array *)array {
+ return [[(GPBInt64Array*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+ return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL count:0];
+}
+
+- (instancetype)initWithValueArray:(GPBInt64Array *)array {
+ return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ if (count && values) {
+ _values = malloc(count * sizeof(int64_t));
+ if (values != NULL) {
+ _capacity = count;
+ memcpy(_values, values, count * sizeof(int64_t));
+ _count = count;
+ } else {
+ [self release];
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(count * sizeof(int64_t))];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+ self = [self initWithValues:NULL count:0];
+ if (self && count) {
+ [self internalResizeToCapacity:count];
+ }
+ return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt64Array allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+ NSAssert(!_autocreator, @"Autocreator must be cleared before release.");
+ free(_values);
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBInt64Array *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt64Array class]]) {
+ return NO;
+ }
+ return (_count == other->_count
+ && memcmp(_values, other->_values, (_count * sizeof(int64_t))) == 0);
+}
+
+- (NSUInteger)hash {
+ // Follow NSArray's lead, and use the count as the hash.
+ return _count;
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ if (i == 0) {
+ [result appendFormat:@"%lld", _values[i]];
+ } else {
+ [result appendFormat:@", %lld", _values[i]];
+ }
+ }
+ [result appendFormat:@" }"];
+ return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block {
+ [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(int64_t value, NSUInteger idx, BOOL *stop))block {
+ // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+ BOOL stop = NO;
+ if ((opts & NSEnumerationReverse) == 0) {
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ block(_values[i], i, &stop);
+ if (stop) break;
+ }
+ } else if (_count > 0) {
+ for (NSUInteger i = _count; i > 0; --i) {
+ block(_values[i - 1], (i - 1), &stop);
+ if (stop) break;
+ }
+ }
+}
+
+- (int64_t)valueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+ _values = reallocf(_values, newCapacity * sizeof(int64_t));
+ if (_values == NULL) {
+ _capacity = 0;
+ _count = 0;
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(newCapacity * sizeof(int64_t))];
+ }
+ _capacity = newCapacity;
+}
+
+- (void)addValue:(int64_t)value {
+ [self addValues:&value count:1];
+}
+
+- (void)addValues:(const int64_t [])values count:(NSUInteger)count {
+ if (values == NULL || count == 0) return;
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + count;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ memcpy(&_values[initialCount], values, count * sizeof(int64_t));
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)insertValue:(int64_t)value atIndex:(NSUInteger)index {
+ if (index >= _count + 1) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count + 1];
+ }
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + 1;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ if (index != initialCount) {
+ memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int64_t));
+ }
+ _values[index] = value;
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int64_t)value {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBInt64Array *)array {
+ [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ NSUInteger newCount = _count - 1;
+ if (index != newCount) {
+ memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int64_t));
+ }
+ _count = newCount;
+ if ((newCount + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+}
+
+- (void)removeAll {
+ _count = 0;
+ if ((0 + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(0)];
+ }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2 {
+ if (idx1 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx1, (unsigned long)_count];
+ }
+ if (idx2 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx2, (unsigned long)_count];
+ }
+ int64_t temp = _values[idx1];
+ _values[idx1] = _values[idx2];
+ _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt64, uint64_t, %llu)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt64
+
+@implementation GPBUInt64Array {
+ @package
+ uint64_t *_values;
+ NSUInteger _count;
+ NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+ return [[[self alloc] initWithValues:NULL count:0] autorelease];
+}
+
++ (instancetype)arrayWithValue:(uint64_t)value {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+ // the type correct.
+ return [[(GPBUInt64Array*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBUInt64Array *)array {
+ return [[(GPBUInt64Array*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+ return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL count:0];
+}
+
+- (instancetype)initWithValueArray:(GPBUInt64Array *)array {
+ return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ if (count && values) {
+ _values = malloc(count * sizeof(uint64_t));
+ if (values != NULL) {
+ _capacity = count;
+ memcpy(_values, values, count * sizeof(uint64_t));
+ _count = count;
+ } else {
+ [self release];
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(count * sizeof(uint64_t))];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+ self = [self initWithValues:NULL count:0];
+ if (self && count) {
+ [self internalResizeToCapacity:count];
+ }
+ return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt64Array allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+ NSAssert(!_autocreator, @"Autocreator must be cleared before release.");
+ free(_values);
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBUInt64Array *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt64Array class]]) {
+ return NO;
+ }
+ return (_count == other->_count
+ && memcmp(_values, other->_values, (_count * sizeof(uint64_t))) == 0);
+}
+
+- (NSUInteger)hash {
+ // Follow NSArray's lead, and use the count as the hash.
+ return _count;
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ if (i == 0) {
+ [result appendFormat:@"%llu", _values[i]];
+ } else {
+ [result appendFormat:@", %llu", _values[i]];
+ }
+ }
+ [result appendFormat:@" }"];
+ return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block {
+ [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(uint64_t value, NSUInteger idx, BOOL *stop))block {
+ // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+ BOOL stop = NO;
+ if ((opts & NSEnumerationReverse) == 0) {
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ block(_values[i], i, &stop);
+ if (stop) break;
+ }
+ } else if (_count > 0) {
+ for (NSUInteger i = _count; i > 0; --i) {
+ block(_values[i - 1], (i - 1), &stop);
+ if (stop) break;
+ }
+ }
+}
+
+- (uint64_t)valueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+ _values = reallocf(_values, newCapacity * sizeof(uint64_t));
+ if (_values == NULL) {
+ _capacity = 0;
+ _count = 0;
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(newCapacity * sizeof(uint64_t))];
+ }
+ _capacity = newCapacity;
+}
+
+- (void)addValue:(uint64_t)value {
+ [self addValues:&value count:1];
+}
+
+- (void)addValues:(const uint64_t [])values count:(NSUInteger)count {
+ if (values == NULL || count == 0) return;
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + count;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ memcpy(&_values[initialCount], values, count * sizeof(uint64_t));
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)insertValue:(uint64_t)value atIndex:(NSUInteger)index {
+ if (index >= _count + 1) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count + 1];
+ }
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + 1;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ if (index != initialCount) {
+ memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(uint64_t));
+ }
+ _values[index] = value;
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(uint64_t)value {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBUInt64Array *)array {
+ [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ NSUInteger newCount = _count - 1;
+ if (index != newCount) {
+ memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(uint64_t));
+ }
+ _count = newCount;
+ if ((newCount + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+}
+
+- (void)removeAll {
+ _count = 0;
+ if ((0 + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(0)];
+ }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2 {
+ if (idx1 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx1, (unsigned long)_count];
+ }
+ if (idx2 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx2, (unsigned long)_count];
+ }
+ uint64_t temp = _values[idx1];
+ _values[idx1] = _values[idx2];
+ _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Float, float, %f)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Float
+
+@implementation GPBFloatArray {
+ @package
+ float *_values;
+ NSUInteger _count;
+ NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+ return [[[self alloc] initWithValues:NULL count:0] autorelease];
+}
+
++ (instancetype)arrayWithValue:(float)value {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+ // the type correct.
+ return [[(GPBFloatArray*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBFloatArray *)array {
+ return [[(GPBFloatArray*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+ return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL count:0];
+}
+
+- (instancetype)initWithValueArray:(GPBFloatArray *)array {
+ return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const float [])values count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ if (count && values) {
+ _values = malloc(count * sizeof(float));
+ if (values != NULL) {
+ _capacity = count;
+ memcpy(_values, values, count * sizeof(float));
+ _count = count;
+ } else {
+ [self release];
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(count * sizeof(float))];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+ self = [self initWithValues:NULL count:0];
+ if (self && count) {
+ [self internalResizeToCapacity:count];
+ }
+ return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBFloatArray allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+ NSAssert(!_autocreator, @"Autocreator must be cleared before release.");
+ free(_values);
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBFloatArray *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBFloatArray class]]) {
+ return NO;
+ }
+ return (_count == other->_count
+ && memcmp(_values, other->_values, (_count * sizeof(float))) == 0);
+}
+
+- (NSUInteger)hash {
+ // Follow NSArray's lead, and use the count as the hash.
+ return _count;
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ if (i == 0) {
+ [result appendFormat:@"%f", _values[i]];
+ } else {
+ [result appendFormat:@", %f", _values[i]];
+ }
+ }
+ [result appendFormat:@" }"];
+ return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block {
+ [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(float value, NSUInteger idx, BOOL *stop))block {
+ // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+ BOOL stop = NO;
+ if ((opts & NSEnumerationReverse) == 0) {
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ block(_values[i], i, &stop);
+ if (stop) break;
+ }
+ } else if (_count > 0) {
+ for (NSUInteger i = _count; i > 0; --i) {
+ block(_values[i - 1], (i - 1), &stop);
+ if (stop) break;
+ }
+ }
+}
+
+- (float)valueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+ _values = reallocf(_values, newCapacity * sizeof(float));
+ if (_values == NULL) {
+ _capacity = 0;
+ _count = 0;
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(newCapacity * sizeof(float))];
+ }
+ _capacity = newCapacity;
+}
+
+- (void)addValue:(float)value {
+ [self addValues:&value count:1];
+}
+
+- (void)addValues:(const float [])values count:(NSUInteger)count {
+ if (values == NULL || count == 0) return;
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + count;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ memcpy(&_values[initialCount], values, count * sizeof(float));
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)insertValue:(float)value atIndex:(NSUInteger)index {
+ if (index >= _count + 1) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count + 1];
+ }
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + 1;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ if (index != initialCount) {
+ memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(float));
+ }
+ _values[index] = value;
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(float)value {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBFloatArray *)array {
+ [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ NSUInteger newCount = _count - 1;
+ if (index != newCount) {
+ memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(float));
+ }
+ _count = newCount;
+ if ((newCount + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+}
+
+- (void)removeAll {
+ _count = 0;
+ if ((0 + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(0)];
+ }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2 {
+ if (idx1 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx1, (unsigned long)_count];
+ }
+ if (idx2 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx2, (unsigned long)_count];
+ }
+ float temp = _values[idx1];
+ _values[idx1] = _values[idx2];
+ _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Double, double, %lf)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Double
+
+@implementation GPBDoubleArray {
+ @package
+ double *_values;
+ NSUInteger _count;
+ NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+ return [[[self alloc] initWithValues:NULL count:0] autorelease];
+}
+
++ (instancetype)arrayWithValue:(double)value {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+ // the type correct.
+ return [[(GPBDoubleArray*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBDoubleArray *)array {
+ return [[(GPBDoubleArray*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+ return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL count:0];
+}
+
+- (instancetype)initWithValueArray:(GPBDoubleArray *)array {
+ return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const double [])values count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ if (count && values) {
+ _values = malloc(count * sizeof(double));
+ if (values != NULL) {
+ _capacity = count;
+ memcpy(_values, values, count * sizeof(double));
+ _count = count;
+ } else {
+ [self release];
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(count * sizeof(double))];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+ self = [self initWithValues:NULL count:0];
+ if (self && count) {
+ [self internalResizeToCapacity:count];
+ }
+ return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBDoubleArray allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+ NSAssert(!_autocreator, @"Autocreator must be cleared before release.");
+ free(_values);
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBDoubleArray *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBDoubleArray class]]) {
+ return NO;
+ }
+ return (_count == other->_count
+ && memcmp(_values, other->_values, (_count * sizeof(double))) == 0);
+}
+
+- (NSUInteger)hash {
+ // Follow NSArray's lead, and use the count as the hash.
+ return _count;
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ if (i == 0) {
+ [result appendFormat:@"%lf", _values[i]];
+ } else {
+ [result appendFormat:@", %lf", _values[i]];
+ }
+ }
+ [result appendFormat:@" }"];
+ return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block {
+ [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(double value, NSUInteger idx, BOOL *stop))block {
+ // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+ BOOL stop = NO;
+ if ((opts & NSEnumerationReverse) == 0) {
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ block(_values[i], i, &stop);
+ if (stop) break;
+ }
+ } else if (_count > 0) {
+ for (NSUInteger i = _count; i > 0; --i) {
+ block(_values[i - 1], (i - 1), &stop);
+ if (stop) break;
+ }
+ }
+}
+
+- (double)valueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+ _values = reallocf(_values, newCapacity * sizeof(double));
+ if (_values == NULL) {
+ _capacity = 0;
+ _count = 0;
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(newCapacity * sizeof(double))];
+ }
+ _capacity = newCapacity;
+}
+
+- (void)addValue:(double)value {
+ [self addValues:&value count:1];
+}
+
+- (void)addValues:(const double [])values count:(NSUInteger)count {
+ if (values == NULL || count == 0) return;
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + count;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ memcpy(&_values[initialCount], values, count * sizeof(double));
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)insertValue:(double)value atIndex:(NSUInteger)index {
+ if (index >= _count + 1) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count + 1];
+ }
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + 1;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ if (index != initialCount) {
+ memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(double));
+ }
+ _values[index] = value;
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(double)value {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBDoubleArray *)array {
+ [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ NSUInteger newCount = _count - 1;
+ if (index != newCount) {
+ memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(double));
+ }
+ _count = newCount;
+ if ((newCount + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+}
+
+- (void)removeAll {
+ _count = 0;
+ if ((0 + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(0)];
+ }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2 {
+ if (idx1 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx1, (unsigned long)_count];
+ }
+ if (idx2 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx2, (unsigned long)_count];
+ }
+ double temp = _values[idx1];
+ _values[idx1] = _values[idx2];
+ _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Bool, BOOL, %d)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool
+
+@implementation GPBBoolArray {
+ @package
+ BOOL *_values;
+ NSUInteger _count;
+ NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+
++ (instancetype)array {
+ return [[[self alloc] initWithValues:NULL count:0] autorelease];
+}
+
++ (instancetype)arrayWithValue:(BOOL)value {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues: on to get
+ // the type correct.
+ return [[(GPBBoolArray*)[self alloc] initWithValues:&value count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBBoolArray *)array {
+ return [[(GPBBoolArray*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithCapacity:(NSUInteger)count {
+ return [[[self alloc] initWithCapacity:count] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL count:0];
+}
+
+- (instancetype)initWithValueArray:(GPBBoolArray *)array {
+ return [self initWithValues:array->_values count:array->_count];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ if (count && values) {
+ _values = malloc(count * sizeof(BOOL));
+ if (values != NULL) {
+ _capacity = count;
+ memcpy(_values, values, count * sizeof(BOOL));
+ _count = count;
+ } else {
+ [self release];
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(count * sizeof(BOOL))];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)count {
+ self = [self initWithValues:NULL count:0];
+ if (self && count) {
+ [self internalResizeToCapacity:count];
+ }
+ return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBBoolArray allocWithZone:zone] initWithValues:_values count:_count];
+}
+
+- (void)dealloc {
+ NSAssert(!_autocreator, @"Autocreator must be cleared before release.");
+ free(_values);
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBBoolArray *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBBoolArray class]]) {
+ return NO;
+ }
+ return (_count == other->_count
+ && memcmp(_values, other->_values, (_count * sizeof(BOOL))) == 0);
+}
+
+- (NSUInteger)hash {
+ // Follow NSArray's lead, and use the count as the hash.
+ return _count;
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ if (i == 0) {
+ [result appendFormat:@"%d", _values[i]];
+ } else {
+ [result appendFormat:@", %d", _values[i]];
+ }
+ }
+ [result appendFormat:@" }"];
+ return result;
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block {
+ [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(BOOL value, NSUInteger idx, BOOL *stop))block {
+ // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+ BOOL stop = NO;
+ if ((opts & NSEnumerationReverse) == 0) {
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ block(_values[i], i, &stop);
+ if (stop) break;
+ }
+ } else if (_count > 0) {
+ for (NSUInteger i = _count; i > 0; --i) {
+ block(_values[i - 1], (i - 1), &stop);
+ if (stop) break;
+ }
+ }
+}
+
+- (BOOL)valueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ return _values[index];
+}
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+ _values = reallocf(_values, newCapacity * sizeof(BOOL));
+ if (_values == NULL) {
+ _capacity = 0;
+ _count = 0;
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(newCapacity * sizeof(BOOL))];
+ }
+ _capacity = newCapacity;
+}
+
+- (void)addValue:(BOOL)value {
+ [self addValues:&value count:1];
+}
+
+- (void)addValues:(const BOOL [])values count:(NSUInteger)count {
+ if (values == NULL || count == 0) return;
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + count;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ memcpy(&_values[initialCount], values, count * sizeof(BOOL));
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)insertValue:(BOOL)value atIndex:(NSUInteger)index {
+ if (index >= _count + 1) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count + 1];
+ }
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + 1;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ if (index != initialCount) {
+ memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(BOOL));
+ }
+ _values[index] = value;
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(BOOL)value {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ _values[index] = value;
+}
+
+- (void)addValuesFromArray:(GPBBoolArray *)array {
+ [self addValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ NSUInteger newCount = _count - 1;
+ if (index != newCount) {
+ memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(BOOL));
+ }
+ _count = newCount;
+ if ((newCount + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+}
+
+- (void)removeAll {
+ _count = 0;
+ if ((0 + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(0)];
+ }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2 {
+ if (idx1 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx1, (unsigned long)_count];
+ }
+ if (idx2 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx2, (unsigned long)_count];
+ }
+ BOOL temp = _values[idx1];
+ _values[idx1] = _values[idx2];
+ _values[idx2] = temp;
+}
+
+@end
+
+//%PDDM-EXPAND-END (7 expansions)
+
+#pragma mark - Enum
+
+@implementation GPBEnumArray {
+ @package
+ GPBEnumValidationFunc _validationFunc;
+ int32_t *_values;
+ NSUInteger _count;
+ NSUInteger _capacity;
+}
+
+@synthesize count = _count;
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)array {
+ return [[[self alloc] initWithValidationFunction:NULL
+ rawValues:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [[[self alloc] initWithValidationFunction:func
+ rawValues:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)value {
+ return [[[self alloc] initWithValidationFunction:func
+ rawValues:&value
+ count:1] autorelease];
+}
+
++ (instancetype)arrayWithValueArray:(GPBEnumArray *)array {
+ return [[(GPBEnumArray*)[self alloc] initWithValueArray:array] autorelease];
+}
+
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)count {
+ return [[[self alloc] initWithValidationFunction:func capacity:count] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValidationFunction:NULL rawValues:NULL count:0];
+}
+
+- (instancetype)initWithValueArray:(GPBEnumArray *)array {
+ return [self initWithValidationFunction:array->_validationFunc
+ rawValues:array->_values
+ count:array->_count];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [self initWithValidationFunction:func rawValues:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _validationFunc = (func != NULL ? func : ArrayDefault_IsValidValue);
+ if (count && values) {
+ _values = malloc(count * sizeof(int32_t));
+ if (values != NULL) {
+ _capacity = count;
+ memcpy(_values, values, count * sizeof(int32_t));
+ _count = count;
+ } else {
+ [self release];
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(count * sizeof(int32_t))];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)count {
+ self = [self initWithValidationFunction:func rawValues:NULL count:0];
+ if (self && count) {
+ [self internalResizeToCapacity:count];
+ }
+ return self;
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBEnumArray allocWithZone:zone]
+ initWithValidationFunction:_validationFunc
+ rawValues:_values
+ count:_count];
+}
+
+//%PDDM-EXPAND ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d)
+// This block of code is generated, do not edit it directly.
+
+- (void)dealloc {
+ NSAssert(!_autocreator, @"Autocreator must be cleared before release.");
+ free(_values);
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(GPBEnumArray *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBEnumArray class]]) {
+ return NO;
+ }
+ return (_count == other->_count
+ && memcmp(_values, other->_values, (_count * sizeof(int32_t))) == 0);
+}
+
+- (NSUInteger)hash {
+ // Follow NSArray's lead, and use the count as the hash.
+ return _count;
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> { ", [self class], self];
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ if (i == 0) {
+ [result appendFormat:@"%d", _values[i]];
+ } else {
+ [result appendFormat:@", %d", _values[i]];
+ }
+ }
+ [result appendFormat:@" }"];
+ return result;
+}
+
+- (void)enumerateRawValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+ [self enumerateRawValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+ // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+ BOOL stop = NO;
+ if ((opts & NSEnumerationReverse) == 0) {
+ for (NSUInteger i = 0, count = _count; i < count; ++i) {
+ block(_values[i], i, &stop);
+ if (stop) break;
+ }
+ } else if (_count > 0) {
+ for (NSUInteger i = _count; i > 0; --i) {
+ block(_values[i - 1], (i - 1), &stop);
+ if (stop) break;
+ }
+ }
+}
+//%PDDM-EXPAND-END ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d)
+
+- (int32_t)valueAtIndex:(NSUInteger)index {
+//%PDDM-EXPAND VALIDATE_RANGE(index, _count)
+// This block of code is generated, do not edit it directly.
+
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+//%PDDM-EXPAND-END VALIDATE_RANGE(index, _count)
+ int32_t result = _values[index];
+ if (!_validationFunc(result)) {
+ result = kGPBUnrecognizedEnumeratorValue;
+ }
+ return result;
+}
+
+- (int32_t)rawValueAtIndex:(NSUInteger)index {
+//%PDDM-EXPAND VALIDATE_RANGE(index, _count)
+// This block of code is generated, do not edit it directly.
+
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+//%PDDM-EXPAND-END VALIDATE_RANGE(index, _count)
+ return _values[index];
+}
+
+- (void)enumerateValuesWithBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+ [self enumerateValuesWithOptions:0 usingBlock:block];
+}
+
+- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+ // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
+ BOOL stop = NO;
+ GPBEnumValidationFunc func = _validationFunc;
+ if ((opts & NSEnumerationReverse) == 0) {
+ int32_t *scan = _values;
+ int32_t *end = scan + _count;
+ for (NSUInteger i = 0; scan < end; ++i, ++scan) {
+ int32_t value = *scan;
+ if (!func(value)) {
+ value = kGPBUnrecognizedEnumeratorValue;
+ }
+ block(value, i, &stop);
+ if (stop) break;
+ }
+ } else if (_count > 0) {
+ int32_t *end = _values;
+ int32_t *scan = end + (_count - 1);
+ for (NSUInteger i = (_count - 1); scan >= end; --i, --scan) {
+ int32_t value = *scan;
+ if (!func(value)) {
+ value = kGPBUnrecognizedEnumeratorValue;
+ }
+ block(value, i, &stop);
+ if (stop) break;
+ }
+ }
+}
+
+//%PDDM-EXPAND ARRAY_MUTABLE_CORE(Enum, int32_t, Raw, %d)
+// This block of code is generated, do not edit it directly.
+
+- (void)internalResizeToCapacity:(NSUInteger)newCapacity {
+ _values = reallocf(_values, newCapacity * sizeof(int32_t));
+ if (_values == NULL) {
+ _capacity = 0;
+ _count = 0;
+ [NSException raise:NSMallocException
+ format:@"Failed to allocate %lu bytes",
+ (unsigned long)(newCapacity * sizeof(int32_t))];
+ }
+ _capacity = newCapacity;
+}
+
+- (void)addRawValue:(int32_t)value {
+ [self addRawValues:&value count:1];
+}
+
+- (void)addRawValues:(const int32_t [])values count:(NSUInteger)count {
+ if (values == NULL || count == 0) return;
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + count;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ memcpy(&_values[initialCount], values, count * sizeof(int32_t));
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)insertRawValue:(int32_t)value atIndex:(NSUInteger)index {
+ if (index >= _count + 1) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count + 1];
+ }
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + 1;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ if (index != initialCount) {
+ memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t));
+ }
+ _values[index] = value;
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withRawValue:(int32_t)value {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ _values[index] = value;
+}
+
+- (void)addRawValuesFromArray:(GPBEnumArray *)array {
+ [self addRawValues:array->_values count:array->_count];
+}
+
+- (void)removeValueAtIndex:(NSUInteger)index {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ NSUInteger newCount = _count - 1;
+ if (index != newCount) {
+ memmove(&_values[index], &_values[index + 1], (newCount - index) * sizeof(int32_t));
+ }
+ _count = newCount;
+ if ((newCount + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+}
+
+- (void)removeAll {
+ _count = 0;
+ if ((0 + (2 * kChunkSize)) < _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(0)];
+ }
+}
+
+- (void)exchangeValueAtIndex:(NSUInteger)idx1
+ withValueAtIndex:(NSUInteger)idx2 {
+ if (idx1 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx1, (unsigned long)_count];
+ }
+ if (idx2 >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)idx2, (unsigned long)_count];
+ }
+ int32_t temp = _values[idx1];
+ _values[idx1] = _values[idx2];
+ _values[idx2] = temp;
+}
+
+//%PDDM-EXPAND MUTATION_METHODS(Enum, int32_t, , EnumValidationList, EnumValidationOne)
+// This block of code is generated, do not edit it directly.
+
+- (void)addValue:(int32_t)value {
+ [self addValues:&value count:1];
+}
+
+- (void)addValues:(const int32_t [])values count:(NSUInteger)count {
+ if (values == NULL || count == 0) return;
+ GPBEnumValidationFunc func = _validationFunc;
+ for (NSUInteger i = 0; i < count; ++i) {
+ if (!func(values[i])) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"%@: Attempt to set an unknown enum value (%d)",
+ [self class], values[i]];
+ }
+ }
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + count;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ memcpy(&_values[initialCount], values, count * sizeof(int32_t));
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)insertValue:(int32_t)value atIndex:(NSUInteger)index {
+ if (index >= _count + 1) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count + 1];
+ }
+ if (!_validationFunc(value)) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"%@: Attempt to set an unknown enum value (%d)",
+ [self class], value];
+ }
+ NSUInteger initialCount = _count;
+ NSUInteger newCount = initialCount + 1;
+ if (newCount > _capacity) {
+ [self internalResizeToCapacity:CapacityFromCount(newCount)];
+ }
+ _count = newCount;;
+ if (index != initialCount) {
+ memmove(&_values[index + 1], &_values[index], (initialCount - index) * sizeof(int32_t));
+ }
+ _values[index] = value;
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)replaceValueAtIndex:(NSUInteger)index withValue:(int32_t)value {
+ if (index >= _count) {
+ [NSException raise:NSRangeException
+ format:@"Index (%lu) beyond bounds (%lu)",
+ (unsigned long)index, (unsigned long)_count];
+ }
+ if (!_validationFunc(value)) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"%@: Attempt to set an unknown enum value (%d)",
+ [self class], value];
+ }
+ _values[index] = value;
+}
+//%PDDM-EXPAND-END (2 expansions)
+
+//%PDDM-DEFINE MUTATION_HOOK_EnumValidationList()
+//% GPBEnumValidationFunc func = _validationFunc;
+//% for (NSUInteger i = 0; i < count; ++i) {
+//% if (!func(values[i])) {
+//% [NSException raise:NSInvalidArgumentException
+//% format:@"%@: Attempt to set an unknown enum value (%d)",
+//% [self class], values[i]];
+//% }
+//% }
+//%
+//%PDDM-DEFINE MUTATION_HOOK_EnumValidationOne()
+//% if (!_validationFunc(value)) {
+//% [NSException raise:NSInvalidArgumentException
+//% format:@"%@: Attempt to set an unknown enum value (%d)",
+//% [self class], value];
+//% }
+//%
+
+@end
+
+#pragma mark - NSArray Subclass
+
+@implementation GPBAutocreatedArray {
+ NSMutableArray *_array;
+}
+
+- (void)dealloc {
+ NSAssert(!_autocreator, @"Autocreator must be cleared before release.");
+ [_array release];
+ [super dealloc];
+}
+
+#pragma mark Required NSArray overrides
+
+- (NSUInteger)count {
+ return [_array count];
+}
+
+- (id)objectAtIndex:(NSUInteger)idx {
+ return [_array objectAtIndex:idx];
+}
+
+#pragma mark Required NSMutableArray overrides
+
+// Only need to call GPBAutocreatedArrayModified() when adding things since
+// we only autocreate empty arrays.
+
+- (void)insertObject:(id)anObject atIndex:(NSUInteger)idx {
+ if (_array == nil) {
+ _array = [[NSMutableArray alloc] init];
+ }
+ [_array insertObject:anObject atIndex:idx];
+
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)removeObject:(id)anObject {
+ [_array removeObject:anObject];
+}
+
+- (void)removeObjectAtIndex:(NSUInteger)idx {
+ [_array removeObjectAtIndex:idx];
+}
+
+- (void)addObject:(id)anObject {
+ if (_array == nil) {
+ _array = [[NSMutableArray alloc] init];
+ }
+ [_array addObject:anObject];
+
+ if (_autocreator) {
+ GPBAutocreatedArrayModified(_autocreator, self);
+ }
+}
+
+- (void)removeLastObject {
+ [_array removeLastObject];
+}
+
+- (void)replaceObjectAtIndex:(NSUInteger)idx withObject:(id)anObject {
+ [_array replaceObjectAtIndex:idx withObject:anObject];
+}
+
+#pragma mark Extra things hooked
+
+- (id)copyWithZone:(NSZone *)zone {
+ if (_array == nil) {
+ _array = [[NSMutableArray alloc] init];
+ }
+ return [_array copyWithZone:zone];
+}
+
+- (id)mutableCopyWithZone:(NSZone *)zone {
+ if (_array == nil) {
+ _array = [[NSMutableArray alloc] init];
+ }
+ return [_array mutableCopyWithZone:zone];
+}
+
+- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
+ objects:(id __unsafe_unretained [])buffer
+ count:(NSUInteger)len {
+ return [_array countByEnumeratingWithState:state objects:buffer count:len];
+}
+
+- (void)enumerateObjectsUsingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
+ [_array enumerateObjectsUsingBlock:block];
+}
+
+- (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts
+ usingBlock:(void (^)(id obj, NSUInteger idx, BOOL *stop))block {
+ [_array enumerateObjectsWithOptions:opts usingBlock:block];
+}
+
+@end
diff --git a/objectivec/GPBArray_PackagePrivate.h b/objectivec/GPBArray_PackagePrivate.h
new file mode 100644
index 00000000..35a45381
--- /dev/null
+++ b/objectivec/GPBArray_PackagePrivate.h
@@ -0,0 +1,130 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBArray.h"
+
+@class GPBMessage;
+
+//%PDDM-DEFINE DECLARE_ARRAY_EXTRAS()
+//%ARRAY_INTERFACE_EXTRAS(Int32, int32_t)
+//%ARRAY_INTERFACE_EXTRAS(UInt32, uint32_t)
+//%ARRAY_INTERFACE_EXTRAS(Int64, int64_t)
+//%ARRAY_INTERFACE_EXTRAS(UInt64, uint64_t)
+//%ARRAY_INTERFACE_EXTRAS(Float, float)
+//%ARRAY_INTERFACE_EXTRAS(Double, double)
+//%ARRAY_INTERFACE_EXTRAS(Bool, BOOL)
+//%ARRAY_INTERFACE_EXTRAS(Enum, int32_t)
+
+//%PDDM-DEFINE ARRAY_INTERFACE_EXTRAS(NAME, TYPE)
+//%#pragma mark - NAME
+//%
+//%@interface GPB##NAME##Array () {
+//% @package
+//% GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+//%}
+//%@end
+//%
+
+//%PDDM-EXPAND DECLARE_ARRAY_EXTRAS()
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32
+
+@interface GPBInt32Array () {
+ @package
+ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - UInt32
+
+@interface GPBUInt32Array () {
+ @package
+ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Int64
+
+@interface GPBInt64Array () {
+ @package
+ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - UInt64
+
+@interface GPBUInt64Array () {
+ @package
+ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Float
+
+@interface GPBFloatArray () {
+ @package
+ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Double
+
+@interface GPBDoubleArray () {
+ @package
+ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Bool
+
+@interface GPBBoolArray () {
+ @package
+ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+#pragma mark - Enum
+
+@interface GPBEnumArray () {
+ @package
+ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
+
+//%PDDM-EXPAND-END DECLARE_ARRAY_EXTRAS()
+
+#pragma mark - NSArray Subclass
+
+@interface GPBAutocreatedArray : NSMutableArray {
+ @package
+ GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
+}
+@end
diff --git a/objectivec/GPBBootstrap.h b/objectivec/GPBBootstrap.h
new file mode 100644
index 00000000..530eb5cb
--- /dev/null
+++ b/objectivec/GPBBootstrap.h
@@ -0,0 +1,84 @@
+// 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.
+
+// The Objective C runtime has complete enough info that most protos don’t end
+// up using this, so leaving it on is no cost or very little cost. If you
+// happen to see it causing bloat, this is the way to disable it. If you do
+// need to disable it, try only disabling it for Release builds as having
+// full TextFormat can be useful for debugging.
+#ifndef GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
+#define GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS 0
+#endif
+
+// Most uses of protocol buffers don't need field options, by default the
+// static data will be compiled out, define this to 1 to include it. The only
+// time you need this is if you are doing introspection of the protocol buffers.
+#ifndef GPBOBJC_INCLUDE_FIELD_OPTIONS
+#define GPBOBJC_INCLUDE_FIELD_OPTIONS 0
+#endif
+
+// Used in the generated code to give sizes to enums. int32_t was chosen based
+// on the fact that Protocol Buffers enums are limited to this range.
+// The complexity and double definition here are so we get the nice name
+// for objective C, but also define the name with a trailing underscore so
+// the Swift bridge will have one where the names line up to support short
+// names since they are scoped to the enum.
+// https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_11
+#define GPB_ENUM(X) enum X##_ : int32_t X; typedef NS_ENUM(int32_t, X##_)
+// GPB_ENUM_FWD_DECLARE is used for forward declaring enums ex:
+// GPB_ENUM_FWD_DECLARE(Foo_Enum)
+// @property (nonatomic) Foo_Enum value;
+#define GPB_ENUM_FWD_DECLARE(_name) enum _name : int32_t
+
+// Based upon CF_INLINE. Forces inlining in release.
+#if !defined(DEBUG)
+#define GPB_INLINE static __inline__ __attribute__((always_inline))
+#else
+#define GPB_INLINE static __inline__
+#endif
+
+// For use in public headers that might need to deal with ARC.
+#ifndef GPB_UNSAFE_UNRETAINED
+#if __has_feature(objc_arc)
+#define GPB_UNSAFE_UNRETAINED __unsafe_unretained
+#else
+#define GPB_UNSAFE_UNRETAINED
+#endif
+#endif
+
+// If property name starts with init we need to annotate it to get past ARC.
+// http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+#define GPB_METHOD_FAMILY_NONE __attribute__((objc_method_family(none)))
+
+// The protoc-gen-objc version which works with the current version of the
+// generated Objective C sources. In general we don't want to change the
+// runtime interfaces (or this version) as it means everything has to be
+// regenerated.
+#define GOOGLE_PROTOBUF_OBJC_GEN_VERSION 30000
diff --git a/objectivec/GPBCodedInputStream.h b/objectivec/GPBCodedInputStream.h
new file mode 100644
index 00000000..db39c268
--- /dev/null
+++ b/objectivec/GPBCodedInputStream.h
@@ -0,0 +1,81 @@
+// 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 <Foundation/Foundation.h>
+
+@class GPBMessage;
+@class GPBExtensionRegistry;
+
+// Reads and decodes protocol message fields.
+// Subclassing of GPBCodedInputStream is NOT supported.
+@interface GPBCodedInputStream : NSObject
+
++ (instancetype)streamWithData:(NSData *)data;
+- (instancetype)initWithData:(NSData *)data;
+
+// Attempt to read a field tag, returning zero if we have reached EOF.
+// Protocol message parsers use this to read tags, since a protocol message
+// may legally end wherever a tag occurs, and zero is not a valid tag number.
+- (int32_t)readTag;
+
+- (double)readDouble;
+- (float)readFloat;
+- (uint64_t)readUInt64;
+- (uint32_t)readUInt32;
+- (int64_t)readInt64;
+- (int32_t)readInt32;
+- (uint64_t)readFixed64;
+- (uint32_t)readFixed32;
+- (int32_t)readEnum;
+- (int32_t)readSFixed32;
+- (int64_t)readSFixed64;
+- (int32_t)readSInt32;
+- (int64_t)readSInt64;
+- (BOOL)readBool;
+- (NSString *)readString;
+- (NSData *)readData;
+
+// Read an embedded message field value from the stream.
+- (void)readMessage:(GPBMessage *)message
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry;
+
+// Reads and discards a single field, given its tag value.
+- (BOOL)skipField:(int32_t)tag;
+
+// Reads and discards an entire message. This will read either until EOF
+// or until an endgroup tag, whichever comes first.
+- (void)skipMessage;
+
+// Verifies that the last call to readTag() returned the given tag value.
+// This is used to verify that a nested group ended with the correct
+// end tag.
+- (void)checkLastTagWas:(int32_t)value;
+
+@end
diff --git a/objectivec/GPBCodedInputStream.m b/objectivec/GPBCodedInputStream.m
new file mode 100644
index 00000000..79d31fc7
--- /dev/null
+++ b/objectivec/GPBCodedInputStream.m
@@ -0,0 +1,801 @@
+// 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 "GPBCodedInputStream_PackagePrivate.h"
+
+#import "GPBDictionary_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+#import "GPBWireFormat.h"
+
+static const NSUInteger kDefaultRecursionLimit = 64;
+
+static inline void CheckSize(GPBCodedInputStreamState *state, size_t size) {
+ size_t newSize = state->bufferPos + size;
+ if (newSize > state->bufferSize) {
+ [NSException raise:NSParseErrorException format:@""];
+ }
+ if (newSize > state->currentLimit) {
+ // Fast forward to end of currentLimit;
+ state->bufferPos = state->currentLimit;
+ [NSException raise:NSParseErrorException format:@""];
+ }
+}
+
+static inline int8_t ReadRawByte(GPBCodedInputStreamState *state) {
+ CheckSize(state, sizeof(int8_t));
+ return ((int8_t *)state->bytes)[state->bufferPos++];
+}
+
+static inline int32_t ReadRawLittleEndian32(GPBCodedInputStreamState *state) {
+ CheckSize(state, sizeof(int32_t));
+ int32_t value = OSReadLittleInt32(state->bytes, state->bufferPos);
+ state->bufferPos += sizeof(int32_t);
+ return value;
+}
+
+static inline int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) {
+ CheckSize(state, sizeof(int64_t));
+ int64_t value = OSReadLittleInt64(state->bytes, state->bufferPos);
+ state->bufferPos += sizeof(int64_t);
+ return value;
+}
+
+static inline int32_t ReadRawVarint32(GPBCodedInputStreamState *state) {
+ int8_t tmp = ReadRawByte(state);
+ if (tmp >= 0) {
+ return tmp;
+ }
+ int32_t result = tmp & 0x7f;
+ if ((tmp = ReadRawByte(state)) >= 0) {
+ result |= tmp << 7;
+ } else {
+ result |= (tmp & 0x7f) << 7;
+ if ((tmp = ReadRawByte(state)) >= 0) {
+ result |= tmp << 14;
+ } else {
+ result |= (tmp & 0x7f) << 14;
+ if ((tmp = ReadRawByte(state)) >= 0) {
+ result |= tmp << 21;
+ } else {
+ result |= (tmp & 0x7f) << 21;
+ result |= (tmp = ReadRawByte(state)) << 28;
+ if (tmp < 0) {
+ // Discard upper 32 bits.
+ for (int i = 0; i < 5; i++) {
+ if (ReadRawByte(state) >= 0) {
+ return result;
+ }
+ }
+ [NSException raise:NSParseErrorException
+ format:@"Unable to read varint32"];
+ }
+ }
+ }
+ }
+ return result;
+}
+
+static inline int64_t ReadRawVarint64(GPBCodedInputStreamState *state) {
+ int32_t shift = 0;
+ int64_t result = 0;
+ while (shift < 64) {
+ int8_t b = ReadRawByte(state);
+ result |= (int64_t)(b & 0x7F) << shift;
+ if ((b & 0x80) == 0) {
+ return result;
+ }
+ shift += 7;
+ }
+ [NSException raise:NSParseErrorException format:@"Unable to read varint64"];
+ return 0;
+}
+
+static inline void SkipRawData(GPBCodedInputStreamState *state, size_t size) {
+ CheckSize(state, size);
+ state->bufferPos += size;
+}
+
+double GPBCodedInputStreamReadDouble(GPBCodedInputStreamState *state) {
+ int64_t value = ReadRawLittleEndian64(state);
+ return GPBConvertInt64ToDouble(value);
+}
+
+float GPBCodedInputStreamReadFloat(GPBCodedInputStreamState *state) {
+ int32_t value = ReadRawLittleEndian32(state);
+ return GPBConvertInt32ToFloat(value);
+}
+
+uint64_t GPBCodedInputStreamReadUInt64(GPBCodedInputStreamState *state) {
+ uint64_t value = ReadRawVarint64(state);
+ return value;
+}
+
+uint32_t GPBCodedInputStreamReadUInt32(GPBCodedInputStreamState *state) {
+ uint32_t value = ReadRawVarint32(state);
+ return value;
+}
+
+int64_t GPBCodedInputStreamReadInt64(GPBCodedInputStreamState *state) {
+ int64_t value = ReadRawVarint64(state);
+ return value;
+}
+
+int32_t GPBCodedInputStreamReadInt32(GPBCodedInputStreamState *state) {
+ int32_t value = ReadRawVarint32(state);
+ return value;
+}
+
+uint64_t GPBCodedInputStreamReadFixed64(GPBCodedInputStreamState *state) {
+ uint64_t value = ReadRawLittleEndian64(state);
+ return value;
+}
+
+uint32_t GPBCodedInputStreamReadFixed32(GPBCodedInputStreamState *state) {
+ uint32_t value = ReadRawLittleEndian32(state);
+ return value;
+}
+
+int32_t GPBCodedInputStreamReadEnum(GPBCodedInputStreamState *state) {
+ int32_t value = ReadRawVarint32(state);
+ return value;
+}
+
+int32_t GPBCodedInputStreamReadSFixed32(GPBCodedInputStreamState *state) {
+ int32_t value = ReadRawLittleEndian32(state);
+ return value;
+}
+
+int64_t GPBCodedInputStreamReadSFixed64(GPBCodedInputStreamState *state) {
+ int64_t value = ReadRawLittleEndian64(state);
+ return value;
+}
+
+int32_t GPBCodedInputStreamReadSInt32(GPBCodedInputStreamState *state) {
+ int32_t value = GPBDecodeZigZag32(ReadRawVarint32(state));
+ return value;
+}
+
+int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state) {
+ int64_t value = GPBDecodeZigZag64(ReadRawVarint64(state));
+ return value;
+}
+
+BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state) {
+ return ReadRawVarint32(state) != 0;
+}
+
+int32_t GPBCodedInputStreamReadTag(GPBCodedInputStreamState *state) {
+ if (GPBCodedInputStreamIsAtEnd(state)) {
+ state->lastTag = 0;
+ return 0;
+ }
+
+ state->lastTag = ReadRawVarint32(state);
+ if (state->lastTag == 0) {
+ // If we actually read zero, that's not a valid tag.
+ [NSException raise:NSParseErrorException
+ format:@"Invalid last tag %d", state->lastTag];
+ }
+ return state->lastTag;
+}
+
+NSString *GPBCodedInputStreamReadRetainedString(
+ GPBCodedInputStreamState *state) {
+ int32_t size = ReadRawVarint32(state);
+ NSString *result;
+ if (size == 0) {
+ result = @"";
+ } else {
+ CheckSize(state, size);
+ result = GPBCreateGPBStringWithUTF8(&state->bytes[state->bufferPos], size);
+ state->bufferPos += size;
+ }
+ return result;
+}
+
+NSData *GPBCodedInputStreamReadRetainedData(GPBCodedInputStreamState *state) {
+ int32_t size = ReadRawVarint32(state);
+ if (size < 0) return nil;
+ CheckSize(state, size);
+ NSData *result = [[NSData alloc] initWithBytes:state->bytes + state->bufferPos
+ length:size];
+ state->bufferPos += size;
+ return result;
+}
+
+NSData *GPBCodedInputStreamReadRetainedDataNoCopy(
+ GPBCodedInputStreamState *state) {
+ int32_t size = ReadRawVarint32(state);
+ if (size < 0) return nil;
+ CheckSize(state, size);
+ // Cast is safe because freeWhenDone is NO.
+ NSData *result = [[NSData alloc]
+ initWithBytesNoCopy:(void *)(state->bytes + state->bufferPos)
+ length:size
+ freeWhenDone:NO];
+ state->bufferPos += size;
+ return result;
+}
+
+size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state,
+ size_t byteLimit) {
+ byteLimit += state->bufferPos;
+ size_t oldLimit = state->currentLimit;
+ if (byteLimit > oldLimit) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"byteLimit > oldLimit: %tu > %tu", byteLimit, oldLimit];
+ }
+ state->currentLimit = byteLimit;
+ return oldLimit;
+}
+
+void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state,
+ size_t oldLimit) {
+ state->currentLimit = oldLimit;
+}
+
+size_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state) {
+ if (state->currentLimit == SIZE_T_MAX) {
+ return state->currentLimit;
+ }
+
+ return state->currentLimit - state->bufferPos;
+}
+
+BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) {
+ return (state->bufferPos == state->bufferSize) ||
+ (state->bufferPos == state->currentLimit);
+}
+
+void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state,
+ int32_t value) {
+ if (state->lastTag != value) {
+ [NSException raise:NSParseErrorException
+ format:@"Last tag: %d should be %d", state->lastTag, value];
+ }
+}
+
+@implementation GPBCodedInputStream
+
++ (instancetype)streamWithData:(NSData *)data {
+ return [[[self alloc] initWithData:data] autorelease];
+}
+
+- (instancetype)initWithData:(NSData *)data {
+ if ((self = [super init])) {
+#ifdef DEBUG
+ NSCAssert([self class] == [GPBCodedInputStream class],
+ @"Subclassing of GPBCodedInputStream is not allowed.");
+#endif
+ buffer_ = [data retain];
+ state_.bytes = (const uint8_t *)[data bytes];
+ state_.bufferSize = [data length];
+ state_.currentLimit = NSUIntegerMax;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [buffer_ release];
+ [super dealloc];
+}
+
+- (int32_t)readTag {
+ return GPBCodedInputStreamReadTag(&state_);
+}
+
+- (void)checkLastTagWas:(int32_t)value {
+ GPBCodedInputStreamCheckLastTagWas(&state_, value);
+}
+
+- (BOOL)skipField:(int32_t)tag {
+ switch (GPBWireFormatGetTagWireType(tag)) {
+ case GPBWireFormatVarint:
+ GPBCodedInputStreamReadInt32(&state_);
+ return YES;
+ case GPBWireFormatFixed64:
+ SkipRawData(&state_, sizeof(int64_t));
+ return YES;
+ case GPBWireFormatLengthDelimited:
+ SkipRawData(&state_, ReadRawVarint32(&state_));
+ return YES;
+ case GPBWireFormatStartGroup:
+ [self skipMessage];
+ GPBCodedInputStreamCheckLastTagWas(
+ &state_, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag),
+ GPBWireFormatEndGroup));
+ return YES;
+ case GPBWireFormatEndGroup:
+ return NO;
+ case GPBWireFormatFixed32:
+ SkipRawData(&state_, sizeof(int32_t));
+ return YES;
+ }
+ [NSException raise:NSParseErrorException format:@"Invalid tag %d", tag];
+ return NO;
+}
+
+- (void)skipMessage {
+ while (YES) {
+ int32_t tag = GPBCodedInputStreamReadTag(&state_);
+ if (tag == 0 || ![self skipField:tag]) {
+ return;
+ }
+ }
+}
+
+- (double)readDouble {
+ return GPBCodedInputStreamReadDouble(&state_);
+}
+
+- (float)readFloat {
+ return GPBCodedInputStreamReadFloat(&state_);
+}
+
+- (uint64_t)readUInt64 {
+ return GPBCodedInputStreamReadUInt64(&state_);
+}
+
+- (int64_t)readInt64 {
+ return GPBCodedInputStreamReadInt64(&state_);
+}
+
+- (int32_t)readInt32 {
+ return GPBCodedInputStreamReadInt32(&state_);
+}
+
+- (uint64_t)readFixed64 {
+ return GPBCodedInputStreamReadFixed64(&state_);
+}
+
+- (uint32_t)readFixed32 {
+ return GPBCodedInputStreamReadFixed32(&state_);
+}
+
+- (BOOL)readBool {
+ return GPBCodedInputStreamReadBool(&state_);
+}
+
+- (NSString *)readString {
+ return [GPBCodedInputStreamReadRetainedString(&state_) autorelease];
+}
+
+- (void)readGroup:(int32_t)fieldNumber
+ message:(GPBMessage *)message
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+ if (state_.recursionDepth >= kDefaultRecursionLimit) {
+ [NSException raise:NSParseErrorException
+ format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth,
+ kDefaultRecursionLimit];
+ }
+ ++state_.recursionDepth;
+ [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
+ GPBCodedInputStreamCheckLastTagWas(
+ &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
+ --state_.recursionDepth;
+}
+
+- (void)readUnknownGroup:(int32_t)fieldNumber
+ message:(GPBUnknownFieldSet *)message {
+ if (state_.recursionDepth >= kDefaultRecursionLimit) {
+ [NSException raise:NSParseErrorException
+ format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth,
+ kDefaultRecursionLimit];
+ }
+ ++state_.recursionDepth;
+ [message mergeFromCodedInputStream:self];
+ GPBCodedInputStreamCheckLastTagWas(
+ &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
+ --state_.recursionDepth;
+}
+
+- (void)readMessage:(GPBMessage *)message
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+ int32_t length = ReadRawVarint32(&state_);
+ if (state_.recursionDepth >= kDefaultRecursionLimit) {
+ [NSException raise:NSParseErrorException
+ format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth,
+ kDefaultRecursionLimit];
+ }
+ size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length);
+ ++state_.recursionDepth;
+ [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
+ GPBCodedInputStreamCheckLastTagWas(&state_, 0);
+ --state_.recursionDepth;
+ GPBCodedInputStreamPopLimit(&state_, oldLimit);
+}
+
+- (void)readMapEntry:(id)mapDictionary
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+ field:(GPBFieldDescriptor *)field
+ parentMessage:(GPBMessage *)parentMessage {
+ int32_t length = ReadRawVarint32(&state_);
+ if (state_.recursionDepth >= kDefaultRecursionLimit) {
+ [NSException raise:NSParseErrorException
+ format:@"recursionDepth(%tu) >= %tu", state_.recursionDepth,
+ kDefaultRecursionLimit];
+ }
+ size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length);
+ ++state_.recursionDepth;
+ GPBDictionaryReadEntry(mapDictionary, self, extensionRegistry, field,
+ parentMessage);
+ GPBCodedInputStreamCheckLastTagWas(&state_, 0);
+ --state_.recursionDepth;
+ GPBCodedInputStreamPopLimit(&state_, oldLimit);
+}
+
+- (NSData *)readData {
+ return [GPBCodedInputStreamReadRetainedData(&state_) autorelease];
+}
+
+- (uint32_t)readUInt32 {
+ return GPBCodedInputStreamReadUInt32(&state_);
+}
+
+- (int32_t)readEnum {
+ return GPBCodedInputStreamReadEnum(&state_);
+}
+
+- (int32_t)readSFixed32 {
+ return GPBCodedInputStreamReadSFixed32(&state_);
+}
+
+- (int64_t)readSFixed64 {
+ return GPBCodedInputStreamReadSFixed64(&state_);
+}
+
+- (int32_t)readSInt32 {
+ return GPBCodedInputStreamReadSInt32(&state_);
+}
+
+- (int64_t)readSInt64 {
+ return GPBCodedInputStreamReadSInt64(&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 inline 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 inline 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
diff --git a/objectivec/GPBCodedInputStream_PackagePrivate.h b/objectivec/GPBCodedInputStream_PackagePrivate.h
new file mode 100644
index 00000000..ba6471ef
--- /dev/null
+++ b/objectivec/GPBCodedInputStream_PackagePrivate.h
@@ -0,0 +1,131 @@
+// 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.
+
+// This header is private to the ProtobolBuffers library and must NOT be
+// included by any sources outside this library. The contents of this file are
+// subject to change at any time without notice.
+
+#import "GPBCodedInputStream.h"
+
+#import <libkern/OSAtomic.h>
+
+@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;
+ size_t bufferPos;
+
+ // For parsing subsections of an input stream you can put a hard limit on
+ // how much should be read. Normally the limit is the end of the stream,
+ // but you can adjust it to anywhere, and if you hit it you will be at the
+ // end of the stream, until you adjust the limit.
+ size_t currentLimit;
+ int32_t lastTag;
+ NSUInteger recursionDepth;
+} GPBCodedInputStreamState;
+
+@interface GPBCodedInputStream () {
+ @package
+ struct GPBCodedInputStreamState state_;
+ NSData *buffer_;
+}
+
+// Group support is deprecated, so we hide this interface from users, but
+// support for older data.
+- (void)readGroup:(int32_t)fieldNumber
+ message:(GPBMessage *)message
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry;
+
+// Reads a group field value from the stream and merges it into the given
+// UnknownFieldSet.
+- (void)readUnknownGroup:(int32_t)fieldNumber
+ message:(GPBUnknownFieldSet *)message;
+
+// Reads a map entry.
+- (void)readMapEntry:(id)mapDictionary
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+ field:(GPBFieldDescriptor *)field
+ parentMessage:(GPBMessage *)parentMessage;
+@end
+
+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);
+float GPBCodedInputStreamReadFloat(GPBCodedInputStreamState *state);
+uint64_t GPBCodedInputStreamReadUInt64(GPBCodedInputStreamState *state);
+uint32_t GPBCodedInputStreamReadUInt32(GPBCodedInputStreamState *state);
+int64_t GPBCodedInputStreamReadInt64(GPBCodedInputStreamState *state);
+int32_t GPBCodedInputStreamReadInt32(GPBCodedInputStreamState *state);
+uint64_t GPBCodedInputStreamReadFixed64(GPBCodedInputStreamState *state);
+uint32_t GPBCodedInputStreamReadFixed32(GPBCodedInputStreamState *state);
+int32_t GPBCodedInputStreamReadEnum(GPBCodedInputStreamState *state);
+int32_t GPBCodedInputStreamReadSFixed32(GPBCodedInputStreamState *state);
+int64_t GPBCodedInputStreamReadSFixed64(GPBCodedInputStreamState *state);
+int32_t GPBCodedInputStreamReadSInt32(GPBCodedInputStreamState *state);
+int64_t GPBCodedInputStreamReadSInt64(GPBCodedInputStreamState *state);
+BOOL GPBCodedInputStreamReadBool(GPBCodedInputStreamState *state);
+NSString *GPBCodedInputStreamReadRetainedString(GPBCodedInputStreamState *state)
+ __attribute((ns_returns_retained));
+NSData *GPBCodedInputStreamReadRetainedData(GPBCodedInputStreamState *state)
+ __attribute((ns_returns_retained));
+NSData *GPBCodedInputStreamReadRetainedDataNoCopy(
+ GPBCodedInputStreamState *state) __attribute((ns_returns_retained));
+
+size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state,
+ size_t byteLimit);
+void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state,
+ size_t oldLimit);
+size_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state);
+BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state);
+void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state,
+ int32_t value);
+
+CF_EXTERN_C_END
diff --git a/objectivec/GPBCodedOutputStream.h b/objectivec/GPBCodedOutputStream.h
new file mode 100644
index 00000000..1f1eb38a
--- /dev/null
+++ b/objectivec/GPBCodedOutputStream.h
@@ -0,0 +1,340 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBTypes.h"
+#import "GPBWireFormat.h"
+
+@class GPBBoolArray;
+@class GPBDoubleArray;
+@class GPBEnumArray;
+@class GPBFloatArray;
+@class GPBMessage;
+@class GPBInt32Array;
+@class GPBInt64Array;
+@class GPBUInt32Array;
+@class GPBUInt64Array;
+@class GPBUnknownFieldSet;
+
+@interface GPBCodedOutputStream : NSObject
+
+// Creates a new stream to write into data. Data must be sized to fit or it
+// will error when it runs out of space.
++ (instancetype)streamWithData:(NSMutableData *)data;
++ (instancetype)streamWithOutputStream:(NSOutputStream *)output;
++ (instancetype)streamWithOutputStream:(NSOutputStream *)output
+ bufferSize:(size_t)bufferSize;
+
+- (instancetype)initWithOutputStream:(NSOutputStream *)output;
+- (instancetype)initWithData:(NSMutableData *)data;
+- (instancetype)initWithOutputStream:(NSOutputStream *)output
+ bufferSize:(size_t)bufferSize;
+- (instancetype)initWithOutputStream:(NSOutputStream *)output
+ data:(NSMutableData *)data;
+
+- (void)flush;
+
+- (void)writeRawByte:(uint8_t)value;
+
+- (void)writeTag:(uint32_t)fieldNumber format:(GPBWireFormat)format;
+
+- (void)writeRawLittleEndian32:(int32_t)value;
+- (void)writeRawLittleEndian64:(int64_t)value;
+
+- (void)writeRawVarint32:(int32_t)value;
+- (void)writeRawVarint64:(int64_t)value;
+
+// Note that this will truncate 64 bit values to 32.
+- (void)writeRawVarintSizeTAs32:(size_t)value;
+
+- (void)writeRawData:(NSData *)data;
+- (void)writeRawPtr:(const void *)data
+ offset:(size_t)offset
+ length:(size_t)length;
+
+//%PDDM-EXPAND _WRITE_DECLS()
+// This block of code is generated, do not edit it directly.
+
+- (void)writeDouble:(int32_t)fieldNumber value:(double)value;
+- (void)writeDoubles:(int32_t)fieldNumber
+ values:(GPBDoubleArray *)values
+ tag:(uint32_t)tag;
+- (void)writeDoubleNoTag:(double)value;
+
+- (void)writeFloat:(int32_t)fieldNumber value:(float)value;
+- (void)writeFloats:(int32_t)fieldNumber
+ values:(GPBFloatArray *)values
+ tag:(uint32_t)tag;
+- (void)writeFloatNoTag:(float)value;
+
+- (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value;
+- (void)writeUInt64s:(int32_t)fieldNumber
+ values:(GPBUInt64Array *)values
+ tag:(uint32_t)tag;
+- (void)writeUInt64NoTag:(uint64_t)value;
+
+- (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value;
+- (void)writeInt64s:(int32_t)fieldNumber
+ values:(GPBInt64Array *)values
+ tag:(uint32_t)tag;
+- (void)writeInt64NoTag:(int64_t)value;
+
+- (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value;
+- (void)writeInt32s:(int32_t)fieldNumber
+ values:(GPBInt32Array *)values
+ tag:(uint32_t)tag;
+- (void)writeInt32NoTag:(int32_t)value;
+
+- (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value;
+- (void)writeUInt32s:(int32_t)fieldNumber
+ values:(GPBUInt32Array *)values
+ tag:(uint32_t)tag;
+- (void)writeUInt32NoTag:(uint32_t)value;
+
+- (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value;
+- (void)writeFixed64s:(int32_t)fieldNumber
+ values:(GPBUInt64Array *)values
+ tag:(uint32_t)tag;
+- (void)writeFixed64NoTag:(uint64_t)value;
+
+- (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value;
+- (void)writeFixed32s:(int32_t)fieldNumber
+ values:(GPBUInt32Array *)values
+ tag:(uint32_t)tag;
+- (void)writeFixed32NoTag:(uint32_t)value;
+
+- (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value;
+- (void)writeSInt32s:(int32_t)fieldNumber
+ values:(GPBInt32Array *)values
+ tag:(uint32_t)tag;
+- (void)writeSInt32NoTag:(int32_t)value;
+
+- (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value;
+- (void)writeSInt64s:(int32_t)fieldNumber
+ values:(GPBInt64Array *)values
+ tag:(uint32_t)tag;
+- (void)writeSInt64NoTag:(int64_t)value;
+
+- (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value;
+- (void)writeSFixed64s:(int32_t)fieldNumber
+ values:(GPBInt64Array *)values
+ tag:(uint32_t)tag;
+- (void)writeSFixed64NoTag:(int64_t)value;
+
+- (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value;
+- (void)writeSFixed32s:(int32_t)fieldNumber
+ values:(GPBInt32Array *)values
+ tag:(uint32_t)tag;
+- (void)writeSFixed32NoTag:(int32_t)value;
+
+- (void)writeBool:(int32_t)fieldNumber value:(BOOL)value;
+- (void)writeBools:(int32_t)fieldNumber
+ values:(GPBBoolArray *)values
+ tag:(uint32_t)tag;
+- (void)writeBoolNoTag:(BOOL)value;
+
+- (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value;
+- (void)writeEnums:(int32_t)fieldNumber
+ values:(GPBEnumArray *)values
+ tag:(uint32_t)tag;
+- (void)writeEnumNoTag:(int32_t)value;
+
+- (void)writeString:(int32_t)fieldNumber value:(NSString *)value;
+- (void)writeStrings:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeStringNoTag:(NSString *)value;
+
+- (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value;
+- (void)writeMessages:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeMessageNoTag:(GPBMessage *)value;
+
+- (void)writeData:(int32_t)fieldNumber value:(NSData *)value;
+- (void)writeDatas:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeDataNoTag:(NSData *)value;
+
+- (void)writeGroup:(int32_t)fieldNumber
+ value:(GPBMessage *)value;
+- (void)writeGroups:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeGroupNoTag:(int32_t)fieldNumber
+ value:(GPBMessage *)value;
+
+- (void)writeUnknownGroup:(int32_t)fieldNumber
+ value:(GPBUnknownFieldSet *)value;
+- (void)writeUnknownGroups:(int32_t)fieldNumber values:(NSArray *)values;
+- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
+ value:(GPBUnknownFieldSet *)value;
+
+//%PDDM-EXPAND-END _WRITE_DECLS()
+
+// Write a MessageSet extension field to the stream. For historical reasons,
+// the wire format differs from normal fields.
+- (void)writeMessageSetExtension:(int32_t)fieldNumber value:(GPBMessage *)value;
+
+// Write an unparsed MessageSet extension field to the stream. For
+// historical reasons, the wire format differs from normal fields.
+- (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value;
+
+@end
+
+CF_EXTERN_C_BEGIN
+
+size_t GPBComputeDoubleSize(int32_t fieldNumber, double value)
+ __attribute__((const));
+size_t GPBComputeFloatSize(int32_t fieldNumber, float value)
+ __attribute__((const));
+size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value)
+ __attribute__((const));
+size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value)
+ __attribute__((const));
+size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value)
+ __attribute__((const));
+size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value)
+ __attribute__((const));
+size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value)
+ __attribute__((const));
+size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value)
+ __attribute__((const));
+size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value)
+ __attribute__((const));
+size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value)
+ __attribute__((const));
+size_t GPBComputeUnknownGroupSize(int32_t fieldNumber,
+ GPBUnknownFieldSet *value)
+ __attribute__((const));
+size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value)
+ __attribute__((const));
+size_t GPBComputeDataSize(int32_t fieldNumber, NSData *value)
+ __attribute__((const));
+size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value)
+ __attribute__((const));
+size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value)
+ __attribute__((const));
+size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value)
+ __attribute__((const));
+size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value)
+ __attribute__((const));
+size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value)
+ __attribute__((const));
+size_t GPBComputeTagSize(int32_t fieldNumber) __attribute__((const));
+size_t GPBComputeWireFormatTagSize(int field_number, GPBType type)
+ __attribute__((const));
+
+size_t GPBComputeDoubleSizeNoTag(double value) __attribute__((const));
+size_t GPBComputeFloatSizeNoTag(float value) __attribute__((const));
+size_t GPBComputeUInt64SizeNoTag(uint64_t value) __attribute__((const));
+size_t GPBComputeInt64SizeNoTag(int64_t value) __attribute__((const));
+size_t GPBComputeInt32SizeNoTag(int32_t value) __attribute__((const));
+size_t GPBComputeFixed64SizeNoTag(uint64_t value) __attribute__((const));
+size_t GPBComputeFixed32SizeNoTag(uint32_t value) __attribute__((const));
+size_t GPBComputeBoolSizeNoTag(BOOL value) __attribute__((const));
+size_t GPBComputeStringSizeNoTag(NSString *value) __attribute__((const));
+size_t GPBComputeGroupSizeNoTag(GPBMessage *value) __attribute__((const));
+size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value)
+ __attribute__((const));
+size_t GPBComputeMessageSizeNoTag(GPBMessage *value) __attribute__((const));
+size_t GPBComputeDataSizeNoTag(NSData *value) __attribute__((const));
+size_t GPBComputeUInt32SizeNoTag(int32_t value) __attribute__((const));
+size_t GPBComputeEnumSizeNoTag(int32_t value) __attribute__((const));
+size_t GPBComputeSFixed32SizeNoTag(int32_t value) __attribute__((const));
+size_t GPBComputeSFixed64SizeNoTag(int64_t value) __attribute__((const));
+size_t GPBComputeSInt32SizeNoTag(int32_t value) __attribute__((const));
+size_t GPBComputeSInt64SizeNoTag(int64_t value) __attribute__((const));
+
+// Note that this will calculate the size of 64 bit values truncated to 32.
+size_t GPBComputeSizeTSizeAsInt32NoTag(size_t value) __attribute__((const));
+
+size_t GPBComputeRawVarint32Size(int32_t value) __attribute__((const));
+size_t GPBComputeRawVarint64Size(int64_t value) __attribute__((const));
+
+// Note that this will calculate the size of 64 bit values truncated to 32.
+size_t GPBComputeRawVarint32SizeForInteger(NSInteger value)
+ __attribute__((const));
+
+// Compute the number of bytes that would be needed to encode a
+// MessageSet extension to the stream. For historical reasons,
+// the wire format differs from normal fields.
+size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber, GPBMessage *value)
+ __attribute__((const));
+
+// Compute the number of bytes that would be needed to encode an
+// unparsed MessageSet extension field to the stream. For
+// historical reasons, the wire format differs from normal fields.
+size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber, NSData *value)
+ __attribute__((const));
+
+size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value)
+ __attribute__((const));
+
+CF_EXTERN_C_END
+
+// Write methods for types that can be in packed arrays.
+//%PDDM-DEFINE _WRITE_PACKABLE_DECLS(NAME, ARRAY_TYPE, TYPE)
+//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value;
+//%- (void)write##NAME##s:(int32_t)fieldNumber
+//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values
+//% NAME$S tag:(uint32_t)tag;
+//%- (void)write##NAME##NoTag:(TYPE)value;
+//%
+// Write methods for types that aren't in packed arrays.
+//%PDDM-DEFINE _WRITE_UNPACKABLE_DECLS(NAME, TYPE)
+//%- (void)write##NAME:(int32_t)fieldNumber value:(TYPE)value;
+//%- (void)write##NAME##s:(int32_t)fieldNumber values:(NSArray *)values;
+//%- (void)write##NAME##NoTag:(TYPE)value;
+//%
+// Special write methods for Groups.
+//%PDDM-DEFINE _WRITE_GROUP_DECLS(NAME, TYPE)
+//%- (void)write##NAME:(int32_t)fieldNumber
+//% NAME$S value:(TYPE)value;
+//%- (void)write##NAME##s:(int32_t)fieldNumber values:(NSArray *)values;
+//%- (void)write##NAME##NoTag:(int32_t)fieldNumber
+//% NAME$S value:(TYPE)value;
+//%
+
+// One macro to hide it all up above.
+//%PDDM-DEFINE _WRITE_DECLS()
+//%_WRITE_PACKABLE_DECLS(Double, Double, double)
+//%_WRITE_PACKABLE_DECLS(Float, Float, float)
+//%_WRITE_PACKABLE_DECLS(UInt64, UInt64, uint64_t)
+//%_WRITE_PACKABLE_DECLS(Int64, Int64, int64_t)
+//%_WRITE_PACKABLE_DECLS(Int32, Int32, int32_t)
+//%_WRITE_PACKABLE_DECLS(UInt32, UInt32, uint32_t)
+//%_WRITE_PACKABLE_DECLS(Fixed64, UInt64, uint64_t)
+//%_WRITE_PACKABLE_DECLS(Fixed32, UInt32, uint32_t)
+//%_WRITE_PACKABLE_DECLS(SInt32, Int32, int32_t)
+//%_WRITE_PACKABLE_DECLS(SInt64, Int64, int64_t)
+//%_WRITE_PACKABLE_DECLS(SFixed64, Int64, int64_t)
+//%_WRITE_PACKABLE_DECLS(SFixed32, Int32, int32_t)
+//%_WRITE_PACKABLE_DECLS(Bool, Bool, BOOL)
+//%_WRITE_PACKABLE_DECLS(Enum, Enum, int32_t)
+//%_WRITE_UNPACKABLE_DECLS(String, NSString *)
+//%_WRITE_UNPACKABLE_DECLS(Message, GPBMessage *)
+//%_WRITE_UNPACKABLE_DECLS(Data, NSData *)
+//%_WRITE_GROUP_DECLS(Group, GPBMessage *)
+//%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet *)
diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m
new file mode 100644
index 00000000..9604c128
--- /dev/null
+++ b/objectivec/GPBCodedOutputStream.m
@@ -0,0 +1,1229 @@
+// 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 "GPBCodedOutputStream.h"
+
+#import <mach/vm_param.h>
+
+#import "GPBArray.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+// Structure for containing state of a GPBCodedInputStream. Brought out into
+// a struct so that we can inline several common functions instead of dealing
+// with overhead of ObjC dispatch.
+typedef struct GPBOutputBufferState {
+ uint8_t *bytes;
+ size_t size;
+ size_t position;
+ NSOutputStream *output;
+} GPBOutputBufferState;
+
+@implementation GPBCodedOutputStream {
+ GPBOutputBufferState state_;
+ NSMutableData *buffer_;
+}
+
+static const int32_t LITTLE_ENDIAN_32_SIZE = sizeof(uint32_t);
+static const int32_t LITTLE_ENDIAN_64_SIZE = sizeof(uint64_t);
+
+// Internal helper that writes the current buffer to the output. The
+// buffer position is reset to its initial value when this returns.
+static void GPBRefreshBuffer(GPBOutputBufferState *state) {
+ if (state->output == nil) {
+ // We're writing to a single buffer.
+ [NSException raise:@"OutOfSpace" format:@""];
+ }
+ if (state->position != 0) {
+ NSInteger written =
+ [state->output write:state->bytes maxLength:state->position];
+ if (written != (NSInteger)state->position) {
+ [NSException raise:@"WriteFailed" format:@""];
+ }
+ state->position = 0;
+ }
+}
+
+static void GPBWriteRawByte(GPBOutputBufferState *state, uint8_t value) {
+ if (state->position == state->size) {
+ GPBRefreshBuffer(state);
+ }
+ state->bytes[state->position++] = value;
+}
+
+static void GPBWriteRawVarint32(GPBOutputBufferState *state, int32_t value) {
+ while (YES) {
+ if ((value & ~0x7F) == 0) {
+ uint8_t val = (uint8_t)value;
+ GPBWriteRawByte(state, val);
+ return;
+ } else {
+ GPBWriteRawByte(state, (value & 0x7F) | 0x80);
+ value = GPBLogicalRightShift32(value, 7);
+ }
+ }
+}
+
+static void GPBWriteRawVarint64(GPBOutputBufferState *state, int64_t value) {
+ while (YES) {
+ if ((value & ~0x7FL) == 0) {
+ uint8_t val = (uint8_t)value;
+ GPBWriteRawByte(state, val);
+ return;
+ } else {
+ GPBWriteRawByte(state, ((int32_t)value & 0x7F) | 0x80);
+ value = GPBLogicalRightShift64(value, 7);
+ }
+ }
+}
+
+static void GPBWriteInt32NoTag(GPBOutputBufferState *state, int32_t value) {
+ if (value >= 0) {
+ GPBWriteRawVarint32(state, value);
+ } else {
+ // Must sign-extend
+ GPBWriteRawVarint64(state, value);
+ }
+}
+
+static void GPBWriteUInt32(GPBOutputBufferState *state, int32_t fieldNumber,
+ uint32_t value) {
+ GPBWriteTagWithFormat(state, fieldNumber, GPBWireFormatVarint);
+ GPBWriteRawVarint32(state, value);
+}
+
+static void GPBWriteTagWithFormat(GPBOutputBufferState *state,
+ uint32_t fieldNumber, GPBWireFormat format) {
+ GPBWriteRawVarint32(state, GPBWireFormatMakeTag(fieldNumber, format));
+}
+
+static void GPBWriteRawLittleEndian32(GPBOutputBufferState *state,
+ int32_t value) {
+ GPBWriteRawByte(state, (value)&0xFF);
+ GPBWriteRawByte(state, (value >> 8) & 0xFF);
+ GPBWriteRawByte(state, (value >> 16) & 0xFF);
+ GPBWriteRawByte(state, (value >> 24) & 0xFF);
+}
+
+static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state,
+ int64_t value) {
+ GPBWriteRawByte(state, (int32_t)(value)&0xFF);
+ GPBWriteRawByte(state, (int32_t)(value >> 8) & 0xFF);
+ GPBWriteRawByte(state, (int32_t)(value >> 16) & 0xFF);
+ GPBWriteRawByte(state, (int32_t)(value >> 24) & 0xFF);
+ GPBWriteRawByte(state, (int32_t)(value >> 32) & 0xFF);
+ GPBWriteRawByte(state, (int32_t)(value >> 40) & 0xFF);
+ GPBWriteRawByte(state, (int32_t)(value >> 48) & 0xFF);
+ GPBWriteRawByte(state, (int32_t)(value >> 56) & 0xFF);
+}
+
+#if DEBUG && !defined(NS_BLOCK_ASSERTIONS)
++ (void)load {
+ // This test exists to verify that CFStrings with embedded NULLs will work
+ // for us. If this Assert fails, all code below that depends on
+ // CFStringGetCStringPtr will NOT work properly on strings that contain
+ // embedded NULLs, and we do get that in some protobufs.
+ // Note that this will not be compiled in release.
+ // We didn't feel that just keeping it in a unit test was sufficient because
+ // the Protobuf unit tests are only run when somebody is actually working
+ // on protobufs.
+ CFStringRef zeroTest = CFSTR("Test\0String");
+ const char *cString = CFStringGetCStringPtr(zeroTest, kCFStringEncodingUTF8);
+ NSAssert(cString == NULL, @"Serious Error");
+}
+#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS)
+
+- (void)dealloc {
+ [self flush];
+ [state_.output close];
+ [state_.output release];
+ [buffer_ release];
+
+ [super dealloc];
+}
+
+- (instancetype)initWithOutputStream:(NSOutputStream *)output {
+ NSMutableData *data = [NSMutableData dataWithLength:PAGE_SIZE];
+ return [self initWithOutputStream:output data:data];
+}
+
+- (instancetype)initWithData:(NSMutableData *)data {
+ return [self initWithOutputStream:nil data:data];
+}
+
+- (instancetype)initWithOutputStream:(NSOutputStream *)output
+ bufferSize:(size_t)bufferSize {
+ NSMutableData *data = [NSMutableData dataWithLength:bufferSize];
+ return [self initWithOutputStream:output data:data];
+}
+
+- (instancetype)initWithOutputStream:(NSOutputStream *)output
+ data:(NSMutableData *)data {
+ if ((self = [super init])) {
+ buffer_ = [data retain];
+ [output open];
+ state_.bytes = [data mutableBytes];
+ state_.size = [data length];
+ state_.output = [output retain];
+ }
+ return self;
+}
+
++ (instancetype)streamWithOutputStream:(NSOutputStream *)output
+ bufferSize:(size_t)bufferSize {
+ return [[[self alloc] initWithOutputStream:output
+ bufferSize:bufferSize] autorelease];
+}
+
++ (instancetype)streamWithOutputStream:(NSOutputStream *)output {
+ return [[[self alloc] initWithOutputStream:output
+ bufferSize:PAGE_SIZE] autorelease];
+}
+
++ (instancetype)streamWithData:(NSMutableData *)data {
+ return [[[self alloc] initWithData:data] autorelease];
+}
+
+- (void)writeDoubleNoTag:(double)value {
+ GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value));
+}
+
+- (void)writeDouble:(int32_t)fieldNumber value:(double)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64);
+ GPBWriteRawLittleEndian64(&state_, GPBConvertDoubleToInt64(value));
+}
+
+- (void)writeFloatNoTag:(float)value {
+ GPBWriteRawLittleEndian32(&state_, GPBConvertFloatToInt32(value));
+}
+
+- (void)writeFloat:(int32_t)fieldNumber value:(float)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32);
+ GPBWriteRawLittleEndian32(&state_, GPBConvertFloatToInt32(value));
+}
+
+- (void)writeUInt64NoTag:(uint64_t)value {
+ GPBWriteRawVarint64(&state_, value);
+}
+
+- (void)writeUInt64:(int32_t)fieldNumber value:(uint64_t)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+ GPBWriteRawVarint64(&state_, value);
+}
+
+- (void)writeInt64NoTag:(int64_t)value {
+ GPBWriteRawVarint64(&state_, value);
+}
+
+- (void)writeInt64:(int32_t)fieldNumber value:(int64_t)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+ GPBWriteRawVarint64(&state_, value);
+}
+
+- (void)writeInt32NoTag:(int32_t)value {
+ GPBWriteInt32NoTag(&state_, value);
+}
+
+- (void)writeInt32:(int32_t)fieldNumber value:(int32_t)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+ GPBWriteInt32NoTag(&state_, value);
+}
+
+- (void)writeFixed64NoTag:(uint64_t)value {
+ GPBWriteRawLittleEndian64(&state_, value);
+}
+
+- (void)writeFixed64:(int32_t)fieldNumber value:(uint64_t)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64);
+ GPBWriteRawLittleEndian64(&state_, value);
+}
+
+- (void)writeFixed32NoTag:(uint32_t)value {
+ GPBWriteRawLittleEndian32(&state_, value);
+}
+
+- (void)writeFixed32:(int32_t)fieldNumber value:(uint32_t)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32);
+ GPBWriteRawLittleEndian32(&state_, value);
+}
+
+- (void)writeBoolNoTag:(BOOL)value {
+ GPBWriteRawByte(&state_, (value ? 1 : 0));
+}
+
+- (void)writeBool:(int32_t)fieldNumber value:(BOOL)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+ GPBWriteRawByte(&state_, (value ? 1 : 0));
+}
+
+- (void)writeStringNoTag:(const NSString *)value {
+ // If you are concerned about embedded NULLs see the test in
+ // +load above.
+ const char *quickString =
+ CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
+ size_t length = (quickString != NULL)
+ ? strlen(quickString)
+ : [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+ GPBWriteRawVarint32(&state_, (int32_t)length);
+
+ if (length == 0) {
+ return;
+ }
+
+ // Fast path: Most strings are short, if the buffer already has space,
+ // add to it directly.
+ NSUInteger bufferBytesLeft = state_.size - state_.position;
+ if (bufferBytesLeft >= length) {
+ NSUInteger usedBufferLength = 0;
+ BOOL result;
+ if (quickString != NULL) {
+ memcpy(state_.bytes + state_.position, quickString, length);
+ usedBufferLength = length;
+ result = YES;
+ } else {
+ result = [value getBytes:state_.bytes + state_.position
+ maxLength:bufferBytesLeft
+ usedLength:&usedBufferLength
+ encoding:NSUTF8StringEncoding
+ options:0
+ range:NSMakeRange(0, [value length])
+ remainingRange:NULL];
+ }
+ if (result) {
+ NSAssert2((usedBufferLength == length),
+ @"Our UTF8 calc was wrong? %tu vs %zd", usedBufferLength,
+ length);
+ state_.position += usedBufferLength;
+ return;
+ }
+ } else if (quickString != NULL) {
+ [self writeRawPtr:quickString offset:0 length:length];
+ } else {
+ // Slow path: just get it as data and write it out.
+ NSData *utf8Data = [value dataUsingEncoding:NSUTF8StringEncoding];
+ NSAssert2(([utf8Data length] == length),
+ @"Strings UTF8 length was wrong? %tu vs %zd", [utf8Data length],
+ length);
+ [self writeRawData:utf8Data];
+ }
+}
+
+- (void)writeString:(int32_t)fieldNumber value:(NSString *)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited);
+ [self writeStringNoTag:value];
+}
+
+- (void)writeGroupNoTag:(int32_t)fieldNumber value:(GPBMessage *)value {
+ [value writeToCodedOutputStream:self];
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup);
+}
+
+- (void)writeGroup:(int32_t)fieldNumber value:(GPBMessage *)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup);
+ [self writeGroupNoTag:fieldNumber value:value];
+}
+
+- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
+ value:(const GPBUnknownFieldSet *)value {
+ [value writeToCodedOutputStream:self];
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup);
+}
+
+- (void)writeUnknownGroup:(int32_t)fieldNumber
+ value:(GPBUnknownFieldSet *)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup);
+ [self writeUnknownGroupNoTag:fieldNumber value:value];
+}
+
+- (void)writeMessageNoTag:(GPBMessage *)value {
+ GPBWriteRawVarint32(&state_, (int32_t)[value serializedSize]);
+ [value writeToCodedOutputStream:self];
+}
+
+- (void)writeMessage:(int32_t)fieldNumber value:(GPBMessage *)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited);
+ [self writeMessageNoTag:value];
+}
+
+- (void)writeDataNoTag:(NSData *)value {
+ GPBWriteRawVarint32(&state_, (int32_t)[value length]);
+ [self writeRawData:value];
+}
+
+- (void)writeData:(int32_t)fieldNumber value:(NSData *)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatLengthDelimited);
+ [self writeDataNoTag:value];
+}
+
+- (void)writeUInt32NoTag:(uint32_t)value {
+ GPBWriteRawVarint32(&state_, value);
+}
+
+- (void)writeUInt32:(int32_t)fieldNumber value:(uint32_t)value {
+ GPBWriteUInt32(&state_, fieldNumber, value);
+}
+
+- (void)writeEnumNoTag:(int32_t)value {
+ GPBWriteRawVarint32(&state_, value);
+}
+
+- (void)writeEnum:(int32_t)fieldNumber value:(int32_t)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+ GPBWriteRawVarint32(&state_, value);
+}
+
+- (void)writeSFixed32NoTag:(int32_t)value {
+ GPBWriteRawLittleEndian32(&state_, value);
+}
+
+- (void)writeSFixed32:(int32_t)fieldNumber value:(int32_t)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed32);
+ GPBWriteRawLittleEndian32(&state_, value);
+}
+
+- (void)writeSFixed64NoTag:(int64_t)value {
+ GPBWriteRawLittleEndian64(&state_, value);
+}
+
+- (void)writeSFixed64:(int32_t)fieldNumber value:(int64_t)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatFixed64);
+ GPBWriteRawLittleEndian64(&state_, value);
+}
+
+- (void)writeSInt32NoTag:(int32_t)value {
+ GPBWriteRawVarint32(&state_, GPBEncodeZigZag32(value));
+}
+
+- (void)writeSInt32:(int32_t)fieldNumber value:(int32_t)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+ GPBWriteRawVarint32(&state_, GPBEncodeZigZag32(value));
+}
+
+- (void)writeSInt64NoTag:(int64_t)value {
+ GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value));
+}
+
+- (void)writeSInt64:(int32_t)fieldNumber value:(int64_t)value {
+ GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatVarint);
+ GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value));
+}
+
+//%PDDM-DEFINE WRITE_PACKABLE_DEFNS(NAME, ARRAY_TYPE, TYPE, ACCESSOR_NAME)
+//%- (void)write##NAME##s:(int32_t)fieldNumber
+//% NAME$S values:(GPB##ARRAY_TYPE##Array *)values
+//% NAME$S tag:(uint32_t)tag {
+//% if (tag != 0) {
+//% if (values.count == 0) return;
+//% __block size_t dataSize = 0;
+//% [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%#pragma unused(idx, stop)
+//% dataSize += GPBCompute##NAME##SizeNoTag(value);
+//% }];
+//% GPBWriteRawVarint32(&state_, tag);
+//% GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+//% [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%#pragma unused(idx, stop)
+//% [self write##NAME##NoTag:value];
+//% }];
+//% } else {
+//% [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//%#pragma unused(idx, stop)
+//% [self write##NAME:fieldNumber value:value];
+//% }];
+//% }
+//%}
+//%
+//%PDDM-DEFINE WRITE_UNPACKABLE_DEFNS(NAME, TYPE)
+//%- (void)write##NAME##s:(int32_t)fieldNumber values:(NSArray *)values {
+//% for (TYPE *value in values) {
+//% [self write##NAME:fieldNumber value:value];
+//% }
+//%}
+//%
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Double, Double, double, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeDoubles:(int32_t)fieldNumber
+ values:(GPBDoubleArray *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeDoubleSizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeDoubleNoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeDouble:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Float, Float, float, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeFloats:(int32_t)fieldNumber
+ values:(GPBFloatArray *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeFloatSizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeFloatNoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeFloat:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt64, UInt64, uint64_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeUInt64s:(int32_t)fieldNumber
+ values:(GPBUInt64Array *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeUInt64SizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeUInt64NoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeUInt64:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int64, Int64, int64_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeInt64s:(int32_t)fieldNumber
+ values:(GPBInt64Array *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeInt64SizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeInt64NoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeInt64:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int32, Int32, int32_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeInt32s:(int32_t)fieldNumber
+ values:(GPBInt32Array *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeInt32SizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeInt32NoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeInt32:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt32, UInt32, uint32_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeUInt32s:(int32_t)fieldNumber
+ values:(GPBUInt32Array *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeUInt32SizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeUInt32NoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeUInt32:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed64, UInt64, uint64_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeFixed64s:(int32_t)fieldNumber
+ values:(GPBUInt64Array *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeFixed64SizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeFixed64NoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeFixed64:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed32, UInt32, uint32_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeFixed32s:(int32_t)fieldNumber
+ values:(GPBUInt32Array *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeFixed32SizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeFixed32NoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeFixed32:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt32, Int32, int32_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeSInt32s:(int32_t)fieldNumber
+ values:(GPBInt32Array *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeSInt32SizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeSInt32NoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeSInt32:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt64, Int64, int64_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeSInt64s:(int32_t)fieldNumber
+ values:(GPBInt64Array *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeSInt64SizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeSInt64NoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeSInt64:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed64, Int64, int64_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeSFixed64s:(int32_t)fieldNumber
+ values:(GPBInt64Array *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeSFixed64SizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeSFixed64NoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeSFixed64:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed32, Int32, int32_t, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeSFixed32s:(int32_t)fieldNumber
+ values:(GPBInt32Array *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeSFixed32SizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeSFixed32NoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeSFixed32:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Bool, Bool, BOOL, )
+// This block of code is generated, do not edit it directly.
+
+- (void)writeBools:(int32_t)fieldNumber
+ values:(GPBBoolArray *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeBoolSizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeBoolNoTag:value];
+ }];
+ } else {
+ [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeBool:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Enum, Enum, int32_t, Raw)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeEnums:(int32_t)fieldNumber
+ values:(GPBEnumArray *)values
+ tag:(uint32_t)tag {
+ if (tag != 0) {
+ if (values.count == 0) return;
+ __block size_t dataSize = 0;
+ [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ dataSize += GPBComputeEnumSizeNoTag(value);
+ }];
+ GPBWriteRawVarint32(&state_, tag);
+ GPBWriteRawVarint32(&state_, (int32_t)dataSize);
+ [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeEnumNoTag:value];
+ }];
+ } else {
+ [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [self writeEnum:fieldNumber value:value];
+ }];
+ }
+}
+
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(String, NSString)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeStrings:(int32_t)fieldNumber values:(NSArray *)values {
+ for (NSString *value in values) {
+ [self writeString:fieldNumber value:value];
+ }
+}
+
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Message, GPBMessage)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeMessages:(int32_t)fieldNumber values:(NSArray *)values {
+ for (GPBMessage *value in values) {
+ [self writeMessage:fieldNumber value:value];
+ }
+}
+
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Data, NSData)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeDatas:(int32_t)fieldNumber values:(NSArray *)values {
+ for (NSData *value in values) {
+ [self writeData:fieldNumber value:value];
+ }
+}
+
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Group, GPBMessage)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeGroups:(int32_t)fieldNumber values:(NSArray *)values {
+ for (GPBMessage *value in values) {
+ [self writeGroup:fieldNumber value:value];
+ }
+}
+
+//%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(UnknownGroup, GPBUnknownFieldSet)
+// This block of code is generated, do not edit it directly.
+
+- (void)writeUnknownGroups:(int32_t)fieldNumber values:(NSArray *)values {
+ for (GPBUnknownFieldSet *value in values) {
+ [self writeUnknownGroup:fieldNumber value:value];
+ }
+}
+
+//%PDDM-EXPAND-END (19 expansions)
+
+- (void)writeMessageSetExtension:(int32_t)fieldNumber
+ value:(GPBMessage *)value {
+ GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
+ GPBWireFormatStartGroup);
+ GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber);
+ [self writeMessage:GPBWireFormatMessageSetMessage value:value];
+ GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
+ GPBWireFormatEndGroup);
+}
+
+- (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value {
+ GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
+ GPBWireFormatStartGroup);
+ GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber);
+ [self writeData:GPBWireFormatMessageSetMessage value:value];
+ GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
+ GPBWireFormatEndGroup);
+}
+
+- (void)flush {
+ if (state_.output != nil) {
+ GPBRefreshBuffer(&state_);
+ }
+}
+
+- (void)writeRawByte:(uint8_t)value {
+ GPBWriteRawByte(&state_, value);
+}
+
+- (void)writeRawData:(const NSData *)data {
+ [self writeRawPtr:[data bytes] offset:0 length:[data length]];
+}
+
+- (void)writeRawPtr:(const void *)value
+ offset:(size_t)offset
+ length:(size_t)length {
+ if (value == nil || length == 0) {
+ return;
+ }
+
+ NSUInteger bufferLength = state_.size;
+ NSUInteger bufferBytesLeft = bufferLength - state_.position;
+ if (bufferBytesLeft >= length) {
+ // We have room in the current buffer.
+ memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset, length);
+ state_.position += length;
+ } else {
+ // Write extends past current buffer. Fill the rest of this buffer and
+ // flush.
+ size_t bytesWritten = bufferBytesLeft;
+ memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset,
+ bytesWritten);
+ offset += bytesWritten;
+ length -= bytesWritten;
+ state_.position = bufferLength;
+ GPBRefreshBuffer(&state_);
+ bufferLength = state_.size;
+
+ // Now deal with the rest.
+ // Since we have an output stream, this is our buffer
+ // and buffer offset == 0
+ if (length <= bufferLength) {
+ // Fits in new buffer.
+ memcpy(state_.bytes, ((uint8_t *)value) + offset, length);
+ state_.position = length;
+ } else {
+ // Write is very big. Let's do it all at once.
+ [state_.output write:((uint8_t *)value) + offset maxLength:length];
+ }
+ }
+}
+
+- (void)writeTag:(uint32_t)fieldNumber format:(GPBWireFormat)format {
+ GPBWriteTagWithFormat(&state_, fieldNumber, format);
+}
+
+- (void)writeRawVarint32:(int32_t)value {
+ GPBWriteRawVarint32(&state_, value);
+}
+
+- (void)writeRawVarintSizeTAs32:(size_t)value {
+ // Note the truncation.
+ GPBWriteRawVarint32(&state_, (int32_t)value);
+}
+
+- (void)writeRawVarint64:(int64_t)value {
+ GPBWriteRawVarint64(&state_, value);
+}
+
+- (void)writeRawLittleEndian32:(int32_t)value {
+ GPBWriteRawLittleEndian32(&state_, value);
+}
+
+- (void)writeRawLittleEndian64:(int64_t)value {
+ GPBWriteRawLittleEndian64(&state_, value);
+}
+
+@end
+
+size_t GPBComputeDoubleSizeNoTag(Float64 value) {
+#pragma unused(value)
+ return LITTLE_ENDIAN_64_SIZE;
+}
+
+size_t GPBComputeFloatSizeNoTag(Float32 value) {
+#pragma unused(value)
+ return LITTLE_ENDIAN_32_SIZE;
+}
+
+size_t GPBComputeUInt64SizeNoTag(uint64_t value) {
+ return GPBComputeRawVarint64Size(value);
+}
+
+size_t GPBComputeInt64SizeNoTag(int64_t value) {
+ return GPBComputeRawVarint64Size(value);
+}
+
+size_t GPBComputeInt32SizeNoTag(int32_t value) {
+ if (value >= 0) {
+ return GPBComputeRawVarint32Size(value);
+ } else {
+ // Must sign-extend.
+ return 10;
+ }
+}
+
+size_t GPBComputeSizeTSizeAsInt32NoTag(size_t value) {
+ return GPBComputeInt32SizeNoTag((int32_t)value);
+}
+
+size_t GPBComputeFixed64SizeNoTag(uint64_t value) {
+#pragma unused(value)
+ return LITTLE_ENDIAN_64_SIZE;
+}
+
+size_t GPBComputeFixed32SizeNoTag(uint32_t value) {
+#pragma unused(value)
+ return LITTLE_ENDIAN_32_SIZE;
+}
+
+size_t GPBComputeBoolSizeNoTag(BOOL value) {
+#pragma unused(value)
+ return 1;
+}
+
+size_t GPBComputeStringSizeNoTag(NSString *value) {
+ // If you are concerned about embedded NULLs see the test in
+ // +load above.
+ const char *quickString =
+ CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
+ NSUInteger length =
+ (quickString != NULL)
+ ? strlen(quickString)
+ : [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
+ return GPBComputeRawVarint32SizeForInteger(length) + length;
+}
+
+size_t GPBComputeGroupSizeNoTag(GPBMessage *value) {
+ return [value serializedSize];
+}
+
+size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) {
+ return value.serializedSize;
+}
+
+size_t GPBComputeMessageSizeNoTag(GPBMessage *value) {
+ size_t size = [value serializedSize];
+ return GPBComputeRawVarint32SizeForInteger(size) + size;
+}
+
+size_t GPBComputeDataSizeNoTag(NSData *value) {
+ NSUInteger valueLength = [value length];
+ return GPBComputeRawVarint32SizeForInteger(valueLength) + valueLength;
+}
+
+size_t GPBComputeUInt32SizeNoTag(int32_t value) {
+ return GPBComputeRawVarint32Size(value);
+}
+
+size_t GPBComputeEnumSizeNoTag(int32_t value) {
+ return GPBComputeRawVarint32Size(value);
+}
+
+size_t GPBComputeSFixed32SizeNoTag(int32_t value) {
+#pragma unused(value)
+ return LITTLE_ENDIAN_32_SIZE;
+}
+
+size_t GPBComputeSFixed64SizeNoTag(int64_t value) {
+#pragma unused(value)
+ return LITTLE_ENDIAN_64_SIZE;
+}
+
+size_t GPBComputeSInt32SizeNoTag(int32_t value) {
+ return GPBComputeRawVarint32Size(GPBEncodeZigZag32(value));
+}
+
+size_t GPBComputeSInt64SizeNoTag(int64_t value) {
+ return GPBComputeRawVarint64Size(GPBEncodeZigZag64(value));
+}
+
+size_t GPBComputeDoubleSize(int32_t fieldNumber, double value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeDoubleSizeNoTag(value);
+}
+
+size_t GPBComputeFloatSize(int32_t fieldNumber, float value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeFloatSizeNoTag(value);
+}
+
+size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeUInt64SizeNoTag(value);
+}
+
+size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeInt64SizeNoTag(value);
+}
+
+size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeInt32SizeNoTag(value);
+}
+
+size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeFixed64SizeNoTag(value);
+}
+
+size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeFixed32SizeNoTag(value);
+}
+
+size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeBoolSizeNoTag(value);
+}
+
+size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeStringSizeNoTag(value);
+}
+
+size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value) {
+ return GPBComputeTagSize(fieldNumber) * 2 + GPBComputeGroupSizeNoTag(value);
+}
+
+size_t GPBComputeUnknownGroupSize(int32_t fieldNumber,
+ GPBUnknownFieldSet *value) {
+ return GPBComputeTagSize(fieldNumber) * 2 +
+ GPBComputeUnknownGroupSizeNoTag(value);
+}
+
+size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeMessageSizeNoTag(value);
+}
+
+size_t GPBComputeDataSize(int32_t fieldNumber, NSData *value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeDataSizeNoTag(value);
+}
+
+size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeUInt32SizeNoTag(value);
+}
+
+size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeEnumSizeNoTag(value);
+}
+
+size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeSFixed32SizeNoTag(value);
+}
+
+size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeSFixed64SizeNoTag(value);
+}
+
+size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value) {
+ return GPBComputeTagSize(fieldNumber) + GPBComputeSInt32SizeNoTag(value);
+}
+
+size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value) {
+ return GPBComputeTagSize(fieldNumber) +
+ GPBComputeRawVarint64Size(GPBEncodeZigZag64(value));
+}
+
+size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber,
+ GPBMessage *value) {
+ return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 +
+ GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) +
+ GPBComputeMessageSize(GPBWireFormatMessageSetMessage, value);
+}
+
+size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber,
+ NSData *value) {
+ return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 +
+ GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) +
+ GPBComputeDataSize(GPBWireFormatMessageSetMessage, value);
+}
+
+size_t GPBComputeTagSize(int32_t fieldNumber) {
+ return GPBComputeRawVarint32Size(
+ GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint));
+}
+
+size_t GPBComputeWireFormatTagSize(int field_number, GPBType type) {
+ size_t result = GPBComputeTagSize(field_number);
+ if (type == GPBTypeGroup) {
+ // Groups have both a start and an end tag.
+ return result * 2;
+ } else {
+ return result;
+ }
+}
+
+size_t GPBComputeRawVarint32Size(int32_t value) {
+ // value is treated as unsigned, so it won't be sign-extended if negative.
+ if ((value & (0xffffffff << 7)) == 0) return 1;
+ if ((value & (0xffffffff << 14)) == 0) return 2;
+ if ((value & (0xffffffff << 21)) == 0) return 3;
+ if ((value & (0xffffffff << 28)) == 0) return 4;
+ return 5;
+}
+
+size_t GPBComputeRawVarint32SizeForInteger(NSInteger value) {
+ // Note the truncation.
+ return GPBComputeRawVarint32Size((int32_t)value);
+}
+
+size_t GPBComputeRawVarint64Size(int64_t value) {
+ if ((value & (0xffffffffffffffffL << 7)) == 0) return 1;
+ if ((value & (0xffffffffffffffffL << 14)) == 0) return 2;
+ if ((value & (0xffffffffffffffffL << 21)) == 0) return 3;
+ if ((value & (0xffffffffffffffffL << 28)) == 0) return 4;
+ if ((value & (0xffffffffffffffffL << 35)) == 0) return 5;
+ if ((value & (0xffffffffffffffffL << 42)) == 0) return 6;
+ if ((value & (0xffffffffffffffffL << 49)) == 0) return 7;
+ if ((value & (0xffffffffffffffffL << 56)) == 0) return 8;
+ if ((value & (0xffffffffffffffffL << 63)) == 0) return 9;
+ return 10;
+}
diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h
new file mode 100644
index 00000000..d8c369c1
--- /dev/null
+++ b/objectivec/GPBDescriptor.h
@@ -0,0 +1,143 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBTypes.h"
+
+@class GPBEnumDescriptor;
+@class GPBFieldDescriptor;
+@class GPBFieldOptions;
+@class GPBFileDescriptor;
+@class GPBOneofDescriptor;
+
+typedef NS_ENUM(NSInteger, GPBFileSyntax) {
+ GPBFileSyntaxUnknown = 0,
+ GPBFileSyntaxProto2 = 2,
+ GPBFileSyntaxProto3 = 3,
+};
+
+typedef NS_ENUM(NSInteger, GPBFieldType) {
+ GPBFieldTypeSingle, // optional/required
+ GPBFieldTypeRepeated, // repeated
+ GPBFieldTypeMap, // map<K,V>
+};
+
+@interface GPBDescriptor : NSObject<NSCopying>
+
+@property(nonatomic, readonly, copy) NSString *name;
+@property(nonatomic, readonly, strong) NSArray *fields;
+@property(nonatomic, readonly, strong) NSArray *oneofs;
+@property(nonatomic, readonly, strong) NSArray *enums;
+@property(nonatomic, readonly, strong) NSArray *extensions;
+@property(nonatomic, readonly) const GPBExtensionRange *extensionRanges;
+@property(nonatomic, readonly) NSUInteger extensionRangesCount;
+@property(nonatomic, readonly, assign) GPBFileDescriptor *file;
+
+@property(nonatomic, readonly, getter=isWireFormat) BOOL wireFormat;
+@property(nonatomic, readonly) Class messageClass;
+
+- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber;
+- (GPBFieldDescriptor *)fieldWithName:(NSString *)name;
+- (GPBOneofDescriptor *)oneofWithName:(NSString *)name;
+- (GPBEnumDescriptor *)enumWithName:(NSString *)name;
+- (GPBFieldDescriptor *)extensionWithNumber:(uint32_t)fieldNumber;
+- (GPBFieldDescriptor *)extensionWithName:(NSString *)name;
+
+@end
+
+@interface GPBFileDescriptor : NSObject
+
+@property(nonatomic, readonly, copy) NSString *package;
+@property(nonatomic, readonly) GPBFileSyntax syntax;
+
+@end
+
+@interface GPBOneofDescriptor : NSObject
+@property(nonatomic, readonly) NSString *name;
+@property(nonatomic, readonly) NSArray *fields;
+
+- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber;
+- (GPBFieldDescriptor *)fieldWithName:(NSString *)name;
+@end
+
+@interface GPBFieldDescriptor : NSObject
+
+@property(nonatomic, readonly, copy) NSString *name;
+@property(nonatomic, readonly) uint32_t number;
+@property(nonatomic, readonly) GPBType type;
+@property(nonatomic, readonly) BOOL hasDefaultValue;
+@property(nonatomic, readonly) GPBValue defaultValue;
+@property(nonatomic, readonly, getter=isRequired) BOOL required;
+@property(nonatomic, readonly, getter=isOptional) BOOL optional;
+@property(nonatomic, readonly) GPBFieldType fieldType;
+// If it is a map, the value type is in -type.
+@property(nonatomic, readonly) GPBType mapKeyType;
+@property(nonatomic, readonly, getter=isPackable) BOOL packable;
+
+@property(nonatomic, readonly, assign) GPBOneofDescriptor *containingOneof;
+
+@property(nonatomic, readonly) GPBFieldOptions *fieldOptions;
+
+// Message properties
+@property(nonatomic, readonly, assign) Class msgClass;
+
+// Enum properties
+@property(nonatomic, readonly, strong) GPBEnumDescriptor *enumDescriptor;
+
+- (BOOL)isValidEnumValue:(int32_t)value;
+
+// For now, this will return nil if it doesn't know the name to use for
+// TextFormat.
+- (NSString *)textFormatName;
+
+@end
+
+@interface GPBEnumDescriptor : NSObject
+
+@property(nonatomic, readonly, copy) NSString *name;
+@property(nonatomic, readonly) GPBEnumValidationFunc enumVerifier;
+
+- (NSString *)enumNameForValue:(int32_t)number;
+- (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name;
+
+- (NSString *)textFormatNameForValue:(int32_t)number;
+
+@end
+
+@interface GPBExtensionDescriptor : NSObject
+@property(nonatomic, readonly) uint32_t fieldNumber;
+@property(nonatomic, readonly) GPBType type;
+@property(nonatomic, readonly, getter=isRepeated) BOOL repeated;
+@property(nonatomic, readonly, getter=isPackable) BOOL packable;
+@property(nonatomic, readonly, assign) Class msgClass;
+@property(nonatomic, readonly) NSString *singletonName;
+@property(nonatomic, readonly, strong) GPBEnumDescriptor *enumDescriptor;
+@end
diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m
new file mode 100644
index 00000000..6730d532
--- /dev/null
+++ b/objectivec/GPBDescriptor.m
@@ -0,0 +1,888 @@
+// 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 "GPBDescriptor_PackagePrivate.h"
+
+#import <objc/runtime.h>
+
+#import "GPBUtilities_PackagePrivate.h"
+#import "GPBWireFormat.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "google/protobuf/Descriptor.pbobjc.h"
+
+// The address of this variable is used as a key for obj_getAssociatedObject.
+static const char kTextFormatExtraValueKey = 0;
+
+// Utility function to generate selectors on the fly.
+static SEL SelFromStrings(const char *prefix, const char *middle,
+ const char *suffix, BOOL takesArg) {
+ if (prefix == NULL && suffix == NULL && !takesArg) {
+ return sel_getUid(middle);
+ }
+ const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0;
+ const size_t middleLen = strlen(middle);
+ const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0;
+ size_t totalLen =
+ prefixLen + middleLen + suffixLen + 1; // include space for null on end.
+ if (takesArg) {
+ totalLen += 1;
+ }
+ char buffer[totalLen];
+ if (prefix != NULL) {
+ memcpy(buffer, prefix, prefixLen);
+ memcpy(buffer + prefixLen, middle, middleLen);
+ buffer[prefixLen] = (char)toupper(buffer[prefixLen]);
+ } else {
+ memcpy(buffer, middle, middleLen);
+ }
+ if (suffix != NULL) {
+ memcpy(buffer + prefixLen + middleLen, suffix, suffixLen);
+ }
+ if (takesArg) {
+ buffer[totalLen - 2] = ':';
+ }
+ // Always null terminate it.
+ buffer[totalLen - 1] = 0;
+
+ SEL result = sel_getUid(buffer);
+ return result;
+}
+
+static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
+ NSArray *allMessageFields)
+ __attribute__((ns_returns_retained));
+
+static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
+ NSArray *allMessageFields) {
+ NSMutableArray *result = [[NSMutableArray alloc] init];
+ for (GPBFieldDescriptor *fieldDesc in allMessageFields) {
+ if (fieldDesc->description_->hasIndex == hasIndex) {
+ [result addObject:fieldDesc];
+ }
+ }
+ return result;
+}
+
+@implementation GPBDescriptor {
+ Class messageClass_;
+ NSArray *enums_;
+ NSArray *extensions_;
+ GPBFileDescriptor *file_;
+ BOOL wireFormat_;
+}
+
+@synthesize messageClass = messageClass_;
+@synthesize fields = fields_;
+@synthesize oneofs = oneofs_;
+@synthesize enums = enums_;
+@synthesize extensions = extensions_;
+@synthesize extensionRanges = extensionRanges_;
+@synthesize extensionRangesCount = extensionRangesCount_;
+@synthesize file = file_;
+@synthesize wireFormat = wireFormat_;
+
++ (instancetype)
+ allocDescriptorForClass:(Class)messageClass
+ rootClass:(Class)rootClass
+ file:(GPBFileDescriptor *)file
+ fields:(GPBMessageFieldDescription *)fieldDescriptions
+ fieldCount:(NSUInteger)fieldCount
+ oneofs:(GPBMessageOneofDescription *)oneofDescriptions
+ oneofCount:(NSUInteger)oneofCount
+ enums:(GPBMessageEnumDescription *)enumDescriptions
+ enumCount:(NSUInteger)enumCount
+ ranges:(const GPBExtensionRange *)ranges
+ rangeCount:(NSUInteger)rangeCount
+ storageSize:(size_t)storageSize
+ wireFormat:(BOOL)wireFormat {
+ NSMutableArray *fields = nil;
+ NSMutableArray *oneofs = nil;
+ NSMutableArray *enums = nil;
+ NSMutableArray *extensionRanges = nil;
+ GPBFileSyntax syntax = file.syntax;
+ for (NSUInteger i = 0; i < fieldCount; ++i) {
+ if (fields == nil) {
+ fields = [[NSMutableArray alloc] initWithCapacity:fieldCount];
+ }
+ GPBFieldDescriptor *fieldDescriptor = [[GPBFieldDescriptor alloc]
+ initWithFieldDescription:&fieldDescriptions[i]
+ rootClass:rootClass
+ syntax:syntax];
+ [fields addObject:fieldDescriptor];
+ [fieldDescriptor release];
+ }
+ for (NSUInteger i = 0; i < oneofCount; ++i) {
+ if (oneofs == nil) {
+ oneofs = [[NSMutableArray alloc] initWithCapacity:oneofCount];
+ }
+ GPBMessageOneofDescription *oneofDescription = &oneofDescriptions[i];
+ NSArray *fieldsForOneof =
+ NewFieldsArrayForHasIndex(oneofDescription->index, fields);
+ GPBOneofDescriptor *oneofDescriptor =
+ [[GPBOneofDescriptor alloc] initWithOneofDescription:oneofDescription
+ fields:fieldsForOneof];
+ [oneofs addObject:oneofDescriptor];
+ [oneofDescriptor release];
+ [fieldsForOneof release];
+ }
+ for (NSUInteger i = 0; i < enumCount; ++i) {
+ if (enums == nil) {
+ enums = [[NSMutableArray alloc] initWithCapacity:enumCount];
+ }
+ GPBEnumDescriptor *enumDescriptor =
+ enumDescriptions[i].enumDescriptorFunc();
+ [enums addObject:enumDescriptor];
+ }
+
+ // TODO(dmaclach): Add support for extensions
+ GPBDescriptor *descriptor = [[self alloc] initWithClass:messageClass
+ file:file
+ fields:fields
+ oneofs:oneofs
+ enums:enums
+ extensions:nil
+ extensionRanges:ranges
+ extensionRangesCount:rangeCount
+ storageSize:storageSize
+ wireFormat:wireFormat];
+ [fields release];
+ [oneofs release];
+ [enums release];
+ [extensionRanges release];
+ return descriptor;
+}
+
++ (instancetype)
+ allocDescriptorForClass:(Class)messageClass
+ rootClass:(Class)rootClass
+ file:(GPBFileDescriptor *)file
+ fields:(GPBMessageFieldDescription *)fieldDescriptions
+ fieldCount:(NSUInteger)fieldCount
+ oneofs:(GPBMessageOneofDescription *)oneofDescriptions
+ oneofCount:(NSUInteger)oneofCount
+ enums:(GPBMessageEnumDescription *)enumDescriptions
+ enumCount:(NSUInteger)enumCount
+ ranges:(const GPBExtensionRange *)ranges
+ rangeCount:(NSUInteger)rangeCount
+ storageSize:(size_t)storageSize
+ wireFormat:(BOOL)wireFormat
+ extraTextFormatInfo:(const char *)extraTextFormatInfo {
+ GPBDescriptor *descriptor = [self allocDescriptorForClass:messageClass
+ rootClass:rootClass
+ file:file
+ fields:fieldDescriptions
+ fieldCount:fieldCount
+ oneofs:oneofDescriptions
+ oneofCount:oneofCount
+ enums:enumDescriptions
+ enumCount:enumCount
+ ranges:ranges
+ rangeCount:rangeCount
+ storageSize:storageSize
+ wireFormat:wireFormat];
+ // Extra info is a compile time option, so skip the work if not needed.
+ if (extraTextFormatInfo) {
+ NSValue *extraInfoValue = [NSValue valueWithPointer:extraTextFormatInfo];
+ for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) {
+ if (fieldDescriptor->description_->flags & GPBFieldTextFormatNameCustom) {
+ objc_setAssociatedObject(fieldDescriptor, &kTextFormatExtraValueKey,
+ extraInfoValue,
+ OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+ }
+ }
+ }
+ return descriptor;
+}
+
+- (instancetype)initWithClass:(Class)messageClass
+ file:(GPBFileDescriptor *)file
+ fields:(NSArray *)fields
+ oneofs:(NSArray *)oneofs
+ enums:(NSArray *)enums
+ extensions:(NSArray *)extensions
+ extensionRanges:(const GPBExtensionRange *)extensionRanges
+ extensionRangesCount:(NSUInteger)extensionRangesCount
+ storageSize:(size_t)storageSize
+ wireFormat:(BOOL)wireFormat {
+ if ((self = [super init])) {
+ messageClass_ = messageClass;
+ file_ = file;
+ fields_ = [fields retain];
+ oneofs_ = [oneofs retain];
+ enums_ = [enums retain];
+ extensions_ = [extensions retain];
+ extensionRanges_ = extensionRanges;
+ extensionRangesCount_ = extensionRangesCount;
+ storageSize_ = storageSize;
+ wireFormat_ = wireFormat;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [fields_ release];
+ [oneofs_ release];
+ [enums_ release];
+ [extensions_ release];
+ [super dealloc];
+}
+
+- (NSString *)name {
+ return NSStringFromClass(messageClass_);
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+#pragma unused(zone)
+ return [self retain];
+}
+
+- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber {
+ for (GPBFieldDescriptor *descriptor in fields_) {
+ if (GPBFieldNumber(descriptor) == fieldNumber) {
+ return descriptor;
+ }
+ }
+ return nil;
+}
+
+- (GPBFieldDescriptor *)fieldWithName:(NSString *)name {
+ for (GPBFieldDescriptor *descriptor in fields_) {
+ if ([descriptor.name isEqual:name]) {
+ return descriptor;
+ }
+ }
+ return nil;
+}
+
+- (GPBOneofDescriptor *)oneofWithName:(NSString *)name {
+ for (GPBOneofDescriptor *descriptor in oneofs_) {
+ if ([descriptor.name isEqual:name]) {
+ return descriptor;
+ }
+ }
+ return nil;
+}
+
+- (GPBEnumDescriptor *)enumWithName:(NSString *)name {
+ for (GPBEnumDescriptor *descriptor in enums_) {
+ if ([descriptor.name isEqual:name]) {
+ return descriptor;
+ }
+ }
+ return nil;
+}
+
+- (GPBFieldDescriptor *)extensionWithNumber:(uint32_t)fieldNumber {
+ for (GPBFieldDescriptor *descriptor in extensions_) {
+ if (GPBFieldNumber(descriptor) == fieldNumber) {
+ return descriptor;
+ }
+ }
+ return nil;
+}
+
+- (GPBFieldDescriptor *)extensionWithName:(NSString *)name {
+ for (GPBFieldDescriptor *descriptor in extensions_) {
+ if ([descriptor.name isEqual:name]) {
+ return descriptor;
+ }
+ }
+ return nil;
+}
+
+@end
+
+@implementation GPBFileDescriptor {
+ NSString *package_;
+ GPBFileSyntax syntax_;
+}
+
+@synthesize package = package_;
+@synthesize syntax = syntax_;
+
+- (instancetype)initWithPackage:(NSString *)package
+ syntax:(GPBFileSyntax)syntax {
+ self = [super init];
+ if (self) {
+ package_ = [package copy];
+ syntax_ = syntax;
+ }
+ return self;
+}
+
+@end
+
+@implementation GPBOneofDescriptor
+
+@synthesize fields = fields_;
+
+- (instancetype)initWithOneofDescription:
+ (GPBMessageOneofDescription *)oneofDescription
+ fields:(NSArray *)fields {
+ self = [super init];
+ if (self) {
+ NSAssert(oneofDescription->index < 0, @"Should always be <0");
+ oneofDescription_ = oneofDescription;
+ fields_ = [fields retain];
+ for (GPBFieldDescriptor *fieldDesc in fields) {
+ fieldDesc->containingOneof_ = self;
+ }
+
+ caseSel_ = SelFromStrings(NULL, oneofDescription->name, "OneOfCase", NO);
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [fields_ release];
+ [super dealloc];
+}
+
+- (NSString *)name {
+ return [NSString stringWithUTF8String:oneofDescription_->name];
+}
+
+- (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber {
+ for (GPBFieldDescriptor *descriptor in fields_) {
+ if (GPBFieldNumber(descriptor) == fieldNumber) {
+ return descriptor;
+ }
+ }
+ return nil;
+}
+
+- (GPBFieldDescriptor *)fieldWithName:(NSString *)name {
+ for (GPBFieldDescriptor *descriptor in fields_) {
+ if ([descriptor.name isEqual:name]) {
+ return descriptor;
+ }
+ }
+ return nil;
+}
+
+@end
+
+uint32_t GPBFieldTag(GPBFieldDescriptor *self) {
+ GPBMessageFieldDescription *description = self->description_;
+ GPBWireFormat format;
+ if ((description->flags & GPBFieldMapKeyMask) != 0) {
+ // Maps are repeated messages on the wire.
+ format = GPBWireFormatForType(GPBTypeMessage, NO);
+ } else {
+ format = GPBWireFormatForType(description->type,
+ description->flags & GPBFieldPacked);
+ }
+ return GPBWireFormatMakeTag(description->number, format);
+}
+
+@implementation GPBFieldDescriptor {
+ GPBValue defaultValue_;
+ GPBFieldOptions *fieldOptions_;
+
+ // Message ivars
+ Class msgClass_;
+
+ // Enum ivars.
+ // If protos are generated with GenerateEnumDescriptors on then it will
+ // be a enumDescriptor, otherwise it will be a enumVerifier.
+ union {
+ GPBEnumDescriptor *enumDescriptor_;
+ GPBEnumValidationFunc enumVerifier_;
+ } enumHandling_;
+}
+
+@synthesize fieldOptions = fieldOptions_;
+@synthesize msgClass = msgClass_;
+@synthesize containingOneof = containingOneof_;
+
+- (instancetype)init {
+ // Throw an exception if people attempt to not use the designated initializer.
+ self = [super init];
+ if (self != nil) {
+ [self doesNotRecognizeSelector:_cmd];
+ self = nil;
+ }
+ return self;
+}
+
+- (instancetype)initWithFieldDescription:
+ (GPBMessageFieldDescription *)description
+ rootClass:(Class)rootClass
+ syntax:(GPBFileSyntax)syntax {
+ if ((self = [super init])) {
+ description_ = description;
+ getSel_ = sel_getUid(description->name);
+ setSel_ = SelFromStrings("set", description->name, NULL, YES);
+
+ if (description->fieldOptions) {
+ // FieldOptions stored as a length prefixed c-escaped string in descriptor
+ // records.
+ uint8_t *optionsBytes = (uint8_t *)description->fieldOptions;
+ uint32_t optionsLength = *((uint32_t *)optionsBytes);
+ // The length is stored in network byte order.
+ optionsLength = ntohl(optionsLength);
+ if (optionsLength > 0) {
+ optionsBytes += sizeof(optionsLength);
+ NSData *optionsData = [NSData dataWithBytesNoCopy:optionsBytes
+ length:optionsLength
+ freeWhenDone:NO];
+ GPBExtensionRegistry *registry = [rootClass extensionRegistry];
+ fieldOptions_ = [[GPBFieldOptions parseFromData:optionsData
+ extensionRegistry:registry] retain];
+ }
+ }
+
+ GPBType type = description->type;
+ BOOL isMessage = GPBTypeIsMessage(type);
+ if (isMessage) {
+ // No has* for repeated/map or something in a oneof (we can't check
+ // containingOneof_ because it isn't set until after initialization).
+ if ((description->hasIndex >= 0) &&
+ (description->hasIndex != GPBNoHasBit)) {
+ hasSel_ = SelFromStrings("has", description->name, NULL, NO);
+ setHasSel_ = SelFromStrings("setHas", description->name, NULL, YES);
+ }
+ const char *className = description->typeSpecific.className;
+ msgClass_ = objc_getClass(className);
+ NSAssert1(msgClass_, @"Class %s not defined", className);
+ // The defaultValue_ is fetched directly in -defaultValue to avoid
+ // initialization order issues.
+ } else {
+ if (!GPBFieldIsMapOrArray(self)) {
+ defaultValue_ = description->defaultValue;
+ if (type == GPBTypeData) {
+ // Data stored as a length prefixed c-string in descriptor records.
+ const uint8_t *bytes = (const uint8_t *)defaultValue_.valueData;
+ if (bytes) {
+ uint32_t length = *((uint32_t *)bytes);
+ // The length is stored in network byte order.
+ length = ntohl(length);
+ bytes += sizeof(length);
+ defaultValue_.valueData =
+ [[NSData alloc] initWithBytes:bytes length:length];
+ }
+ }
+ // No has* methods for proto3 or if our hasIndex is < 0 because it
+ // means the field is in a oneof (we can't check containingOneof_
+ // because it isn't set until after initialization).
+ if ((syntax != GPBFileSyntaxProto3) && (description->hasIndex >= 0) &&
+ (description->hasIndex != GPBNoHasBit)) {
+ hasSel_ = SelFromStrings("has", description->name, NULL, NO);
+ setHasSel_ = SelFromStrings("setHas", description->name, NULL, YES);
+ }
+ }
+ if (GPBTypeIsEnum(type)) {
+ if (description_->flags & GPBFieldHasEnumDescriptor) {
+ enumHandling_.enumDescriptor_ =
+ description->typeSpecific.enumDescFunc();
+ } else {
+ enumHandling_.enumVerifier_ = description->typeSpecific.enumVerifier;
+ }
+ }
+ }
+ }
+ return self;
+}
+
+- (void)dealloc {
+ if (description_->type == GPBTypeData &&
+ !(description_->flags & GPBFieldRepeated)) {
+ [defaultValue_.valueData release];
+ }
+ [super dealloc];
+}
+
+- (GPBType)type {
+ return description_->type;
+}
+
+- (BOOL)hasDefaultValue {
+ return (description_->flags & GPBFieldHasDefaultValue) != 0;
+}
+
+- (uint32_t)number {
+ return description_->number;
+}
+
+- (NSString *)name {
+ return [NSString stringWithUTF8String:description_->name];
+}
+
+- (BOOL)isRequired {
+ return (description_->flags & GPBFieldRequired) != 0;
+}
+
+- (BOOL)isOptional {
+ return (description_->flags & GPBFieldOptional) != 0;
+}
+
+- (GPBFieldType)fieldType {
+ GPBFieldFlags flags = description_->flags;
+ if ((flags & GPBFieldRepeated) != 0) {
+ return GPBFieldTypeRepeated;
+ } else if ((flags & GPBFieldMapKeyMask) != 0) {
+ return GPBFieldTypeMap;
+ } else {
+ return GPBFieldTypeSingle;
+ }
+}
+
+- (GPBType)mapKeyType {
+ switch (description_->flags & GPBFieldMapKeyMask) {
+ case GPBFieldMapKeyInt32:
+ return GPBTypeInt32;
+ case GPBFieldMapKeyInt64:
+ return GPBTypeInt64;
+ case GPBFieldMapKeyUInt32:
+ return GPBTypeUInt32;
+ case GPBFieldMapKeyUInt64:
+ return GPBTypeUInt64;
+ case GPBFieldMapKeySInt32:
+ return GPBTypeSInt32;
+ case GPBFieldMapKeySInt64:
+ return GPBTypeSInt64;
+ case GPBFieldMapKeyFixed32:
+ return GPBTypeFixed32;
+ case GPBFieldMapKeyFixed64:
+ return GPBTypeFixed64;
+ case GPBFieldMapKeySFixed32:
+ return GPBTypeSFixed32;
+ case GPBFieldMapKeySFixed64:
+ return GPBTypeSFixed64;
+ case GPBFieldMapKeyBool:
+ return GPBTypeBool;
+ case GPBFieldMapKeyString:
+ return GPBTypeString;
+
+ default:
+ NSAssert(0, @"Not a map type");
+ return GPBTypeInt32; // For lack of anything better.
+ }
+}
+
+- (BOOL)isPackable {
+ return (description_->flags & GPBFieldPacked) != 0;
+}
+
+- (BOOL)isValidEnumValue:(int32_t)value {
+ NSAssert(description_->type == GPBTypeEnum,
+ @"Field Must be of type GPBTypeEnum");
+ if (description_->flags & GPBFieldHasEnumDescriptor) {
+ return enumHandling_.enumDescriptor_.enumVerifier(value);
+ } else {
+ return enumHandling_.enumVerifier_(value);
+ }
+}
+
+- (GPBEnumDescriptor *)enumDescriptor {
+ if (description_->flags & GPBFieldHasEnumDescriptor) {
+ return enumHandling_.enumDescriptor_;
+ } else {
+ return nil;
+ }
+}
+
+- (GPBValue)defaultValue {
+ // Depends on the fact that defaultValue_ is initialized either to "0/nil" or
+ // to an actual defaultValue in our initializer.
+ GPBValue value = defaultValue_;
+
+ if (!(description_->flags & GPBFieldRepeated)) {
+ // We special handle data and strings. If they are nil, we replace them
+ // with empty string/empty data.
+ GPBType type = description_->type;
+ if (type == GPBTypeData && value.valueData == nil) {
+ value.valueData = GPBEmptyNSData();
+ } else if (type == GPBTypeString && value.valueString == nil) {
+ value.valueString = @"";
+ }
+ }
+ return value;
+}
+
+- (NSString *)textFormatName {
+ if ((description_->flags & GPBFieldTextFormatNameCustom) != 0) {
+ NSValue *extraInfoValue =
+ objc_getAssociatedObject(self, &kTextFormatExtraValueKey);
+ // Support can be left out at generation time.
+ if (!extraInfoValue) {
+ return nil;
+ }
+ const uint8_t *extraTextFormatInfo = [extraInfoValue pointerValue];
+ return GPBDecodeTextFormatName(extraTextFormatInfo, GPBFieldNumber(self),
+ self.name);
+ }
+
+ // The logic here has to match SetCommonFieldVariables() from
+ // objectivec_field.cc in the proto compiler.
+ NSString *name = self.name;
+ NSUInteger len = [name length];
+
+ // Remove the "_p" added to reserved names.
+ if ([name hasSuffix:@"_p"]) {
+ name = [name substringToIndex:(len - 2)];
+ len = [name length];
+ }
+
+ // Remove "Array" from the end for repeated fields.
+ if (((description_->flags & GPBFieldRepeated) != 0) &&
+ [name hasSuffix:@"Array"]) {
+ name = [name substringToIndex:(len - 5)];
+ len = [name length];
+ }
+
+ // Groups vs. other fields.
+ if (description_->type == GPBTypeGroup) {
+ // Just capitalize the first letter.
+ unichar firstChar = [name characterAtIndex:0];
+ if (firstChar >= 'a' && firstChar <= 'z') {
+ NSString *firstCharString =
+ [NSString stringWithFormat:@"%C", (unichar)(firstChar - 'a' + 'A')];
+ NSString *result =
+ [name stringByReplacingCharactersInRange:NSMakeRange(0, 1)
+ withString:firstCharString];
+ return result;
+ }
+ return name;
+
+ } else {
+ // Undo the CamelCase.
+ NSMutableString *result = [NSMutableString stringWithCapacity:len];
+ for (NSUInteger i = 0; i < len; i++) {
+ unichar c = [name characterAtIndex:i];
+ if (c >= 'A' && c <= 'Z') {
+ if (i > 0) {
+ [result appendFormat:@"_%C", (unichar)(c - 'A' + 'a')];
+ } else {
+ [result appendFormat:@"%C", c];
+ }
+ } else {
+ [result appendFormat:@"%C", c];
+ }
+ }
+ return result;
+ }
+}
+
+@end
+
+@implementation GPBEnumDescriptor {
+ NSString *name_;
+ GPBMessageEnumValueDescription *valueDescriptions_;
+ NSUInteger valueDescriptionsCount_;
+ GPBEnumValidationFunc enumVerifier_;
+ const uint8_t *extraTextFormatInfo_;
+}
+
+@synthesize name = name_;
+@synthesize enumVerifier = enumVerifier_;
+
++ (instancetype)
+ allocDescriptorForName:(NSString *)name
+ values:(GPBMessageEnumValueDescription *)valueDescriptions
+ valueCount:(NSUInteger)valueCount
+ enumVerifier:(GPBEnumValidationFunc)enumVerifier {
+ GPBEnumDescriptor *descriptor = [[self alloc] initWithName:name
+ values:valueDescriptions
+ valueCount:valueCount
+ enumVerifier:enumVerifier];
+ return descriptor;
+}
+
++ (instancetype)
+ allocDescriptorForName:(NSString *)name
+ values:(GPBMessageEnumValueDescription *)valueDescriptions
+ valueCount:(NSUInteger)valueCount
+ enumVerifier:(GPBEnumValidationFunc)enumVerifier
+ extraTextFormatInfo:(const char *)extraTextFormatInfo {
+ // Call the common case.
+ GPBEnumDescriptor *descriptor = [self allocDescriptorForName:name
+ values:valueDescriptions
+ valueCount:valueCount
+ enumVerifier:enumVerifier];
+ // Set the extra info.
+ descriptor->extraTextFormatInfo_ = (const uint8_t *)extraTextFormatInfo;
+ return descriptor;
+}
+
+- (instancetype)initWithName:(NSString *)name
+ values:(GPBMessageEnumValueDescription *)valueDescriptions
+ valueCount:(NSUInteger)valueCount
+ enumVerifier:(GPBEnumValidationFunc)enumVerifier {
+ if ((self = [super init])) {
+ name_ = [name copy];
+ valueDescriptions_ = valueDescriptions;
+ valueDescriptionsCount_ = valueCount;
+ enumVerifier_ = enumVerifier;
+ }
+ return self;
+}
+
+- (NSString *)enumNameForValue:(int32_t)number {
+ for (NSUInteger i = 0; i < valueDescriptionsCount_; ++i) {
+ GPBMessageEnumValueDescription *scan = &valueDescriptions_[i];
+ if ((scan->number == number) && (scan->name != NULL)) {
+ NSString *fullName =
+ [NSString stringWithFormat:@"%@_%s", name_, scan->name];
+ return fullName;
+ }
+ }
+ return nil;
+}
+
+- (BOOL)getValue:(int32_t *)outValue forEnumName:(NSString *)name {
+ // Must have the prefix.
+ NSUInteger prefixLen = name_.length + 1;
+ if ((name.length <= prefixLen) || ![name hasPrefix:name_] ||
+ ([name characterAtIndex:prefixLen - 1] != '_')) {
+ return NO;
+ }
+
+ // Skip over the prefix.
+ const char *nameAsCStr = [name UTF8String];
+ nameAsCStr += prefixLen;
+
+ // Find it.
+ for (NSUInteger i = 0; i < valueDescriptionsCount_; ++i) {
+ GPBMessageEnumValueDescription *scan = &valueDescriptions_[i];
+ if ((scan->name != NULL) && (strcmp(nameAsCStr, scan->name) == 0)) {
+ if (outValue) {
+ *outValue = scan->number;
+ }
+ return YES;
+ }
+ }
+ return NO;
+}
+
+- (void)dealloc {
+ [name_ release];
+ [super dealloc];
+}
+
+- (NSString *)textFormatNameForValue:(int32_t)number {
+ // Find the EnumValue descriptor and its index.
+ GPBMessageEnumValueDescription *valueDescriptor = NULL;
+ NSUInteger valueDescriptorIndex;
+ for (valueDescriptorIndex = 0; valueDescriptorIndex < valueDescriptionsCount_;
+ ++valueDescriptorIndex) {
+ GPBMessageEnumValueDescription *scan =
+ &valueDescriptions_[valueDescriptorIndex];
+ if (scan->number == number) {
+ valueDescriptor = scan;
+ break;
+ }
+ }
+
+ // If we didn't find it, or names were disable at proto compile time, nothing
+ // we can do.
+ if (!valueDescriptor || !valueDescriptor->name) {
+ return nil;
+ }
+
+ NSString *result = nil;
+ // Naming adds an underscore between enum name and value name, skip that also.
+ NSString *shortName = [NSString stringWithUTF8String:valueDescriptor->name];
+
+ // See if it is in the map of special format handling.
+ if (extraTextFormatInfo_) {
+ result = GPBDecodeTextFormatName(extraTextFormatInfo_,
+ (int32_t)valueDescriptorIndex, shortName);
+ }
+ // Logic here needs to match what objectivec_enum.cc does in the proto
+ // compiler.
+ if (result == nil) {
+ NSUInteger len = [shortName length];
+ NSMutableString *worker = [NSMutableString stringWithCapacity:len];
+ for (NSUInteger i = 0; i < len; i++) {
+ unichar c = [shortName characterAtIndex:i];
+ if (i > 0 && c >= 'A' && c <= 'Z') {
+ [worker appendString:@"_"];
+ }
+ [worker appendFormat:@"%c", toupper((char)c)];
+ }
+ result = worker;
+ }
+ return result;
+}
+
+@end
+
+@implementation GPBExtensionDescriptor
+
+- (instancetype)initWithExtensionDescription:
+ (GPBExtensionDescription *)description {
+ if ((self = [super init])) {
+ description_ = description;
+ }
+ return self;
+}
+
+- (NSString *)singletonName {
+ return [NSString stringWithUTF8String:description_->singletonName];
+}
+
+- (const char *)singletonNameC {
+ return description_->singletonName;
+}
+
+- (uint32_t)fieldNumber {
+ return description_->fieldNumber;
+}
+
+- (GPBType)type {
+ return description_->type;
+}
+
+- (BOOL)isRepeated {
+ return (description_->options & GPBExtensionRepeated) != 0;
+}
+
+- (BOOL)isMap {
+ return (description_->options & GPBFieldMapKeyMask) != 0;
+}
+
+- (BOOL)isPackable {
+ return (description_->options & GPBExtensionPacked) != 0;
+}
+
+- (Class)msgClass {
+ return objc_getClass(description_->messageOrGroupClassName);
+}
+
+- (GPBEnumDescriptor *)enumDescriptor {
+ if (GPBTypeIsEnum(description_->type)) {
+ GPBEnumDescriptor *enumDescriptor = description_->enumDescriptorFunc();
+ return enumDescriptor;
+ }
+ return nil;
+}
+
+@end
diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h
new file mode 100644
index 00000000..acb4fe70
--- /dev/null
+++ b/objectivec/GPBDescriptor_PackagePrivate.h
@@ -0,0 +1,293 @@
+// 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.
+
+// This header is private to the ProtobolBuffers library and must NOT be
+// included by any sources outside this library. The contents of this file are
+// subject to change at any time without notice.
+
+#import "GPBDescriptor.h"
+
+// Describes attributes of the field.
+typedef NS_OPTIONS(uint32_t, GPBFieldFlags) {
+ // These map to standard protobuf concepts.
+ GPBFieldRequired = 1 << 0,
+ GPBFieldRepeated = 1 << 1,
+ GPBFieldPacked = 1 << 2,
+ GPBFieldOptional = 1 << 3,
+ GPBFieldHasDefaultValue = 1 << 4,
+
+ // These are not standard protobuf concepts, they are specific to the
+ // Objective C runtime.
+
+ // These bits are used to mark the field as a map and what the key
+ // type is.
+ GPBFieldMapKeyMask = 0xF << 8,
+ GPBFieldMapKeyInt32 = 1 << 8,
+ GPBFieldMapKeyInt64 = 2 << 8,
+ GPBFieldMapKeyUInt32 = 3 << 8,
+ GPBFieldMapKeyUInt64 = 4 << 8,
+ GPBFieldMapKeySInt32 = 5 << 8,
+ GPBFieldMapKeySInt64 = 6 << 8,
+ GPBFieldMapKeyFixed32 = 7 << 8,
+ GPBFieldMapKeyFixed64 = 8 << 8,
+ GPBFieldMapKeySFixed32 = 9 << 8,
+ GPBFieldMapKeySFixed64 = 10 << 8,
+ GPBFieldMapKeyBool = 11 << 8,
+ GPBFieldMapKeyString = 12 << 8,
+
+ // Indicates the field needs custom handling for the TextFormat name, if not
+ // set, the name can be derived from the ObjC name.
+ GPBFieldTextFormatNameCustom = 1 << 16,
+ // Indicates the field has an enum descriptor.
+ // TODO(thomasvl): Output the CPP check to use descFunc or validator based
+ // on final compile. This will then get added based on that.
+ GPBFieldHasEnumDescriptor = 1 << 17,
+};
+
+// Describes a single field in a protobuf as it is represented as an ivar.
+typedef struct GPBMessageFieldDescription {
+ // Name of ivar.
+ const char *name;
+ // The field number for the ivar.
+ uint32_t number;
+ // The index (in bits) into _has_storage_.
+ // > 0: the bit to use for a value being set.
+ // = 0: no storage used.
+ // < 0: in a oneOf, use a full int32 to record the field active.
+ int32_t hasIndex;
+ // Field flags. Use accessor functions below.
+ GPBFieldFlags flags;
+ // Type of the ivar.
+ GPBType type;
+ // Offset of the variable into it's structure struct.
+ size_t offset;
+ // FieldOptions protobuf, serialized as string.
+ const char *fieldOptions;
+
+ GPBValue defaultValue; // Default value for the ivar.
+ union {
+ const char *className; // Name for message class.
+ // For enums only: If EnumDescriptors are compiled in, it will be that,
+ // otherwise it will be the verifier.
+ GPBEnumDescriptorFunc enumDescFunc;
+ GPBEnumValidationFunc enumVerifier;
+ } typeSpecific;
+} GPBMessageFieldDescription;
+
+// Describes a oneof.
+typedef struct GPBMessageOneofDescription {
+ // Name of this enum oneof.
+ const char *name;
+ // The index of this oneof in the has_storage.
+ int32_t index;
+} GPBMessageOneofDescription;
+
+// Describes an enum type defined in a .proto file.
+typedef struct GPBMessageEnumDescription {
+ GPBEnumDescriptorFunc enumDescriptorFunc;
+} GPBMessageEnumDescription;
+
+// Describes an individual enum constant of a particular type.
+typedef struct GPBMessageEnumValueDescription {
+ // Name of this enum constant.
+ const char *name;
+ // Numeric value of this enum constant.
+ int32_t number;
+} GPBMessageEnumValueDescription;
+
+// Describes attributes of the extension.
+typedef NS_OPTIONS(uint32_t, GPBExtensionOptions) {
+ // These map to standard protobuf concepts.
+ GPBExtensionRepeated = 1 << 0,
+ GPBExtensionPacked = 1 << 1,
+ GPBExtensionSetWireFormat = 1 << 2,
+};
+
+// An extension
+typedef struct GPBExtensionDescription {
+ const char *singletonName;
+ GPBType type;
+ const char *extendedClass;
+ int32_t fieldNumber;
+ GPBValue defaultValue;
+ const char *messageOrGroupClassName;
+ GPBExtensionOptions options;
+ GPBEnumDescriptorFunc enumDescriptorFunc;
+} GPBExtensionDescription;
+
+@interface GPBDescriptor () {
+ @package
+ NSArray *fields_;
+ NSArray *oneofs_;
+ size_t storageSize_;
+}
+
+// fieldDescriptions, enumDescriptions, rangeDescriptions, and
+// extraTextFormatInfo have to be long lived, they are held as raw pointers.
++ (instancetype)
+ allocDescriptorForClass:(Class)messageClass
+ rootClass:(Class)rootClass
+ file:(GPBFileDescriptor *)file
+ fields:(GPBMessageFieldDescription *)fieldDescriptions
+ fieldCount:(NSUInteger)fieldCount
+ oneofs:(GPBMessageOneofDescription *)oneofDescriptions
+ oneofCount:(NSUInteger)oneofCount
+ enums:(GPBMessageEnumDescription *)enumDescriptions
+ enumCount:(NSUInteger)enumCount
+ ranges:(const GPBExtensionRange *)ranges
+ rangeCount:(NSUInteger)rangeCount
+ storageSize:(size_t)storageSize
+ wireFormat:(BOOL)wireFormat;
++ (instancetype)
+ allocDescriptorForClass:(Class)messageClass
+ rootClass:(Class)rootClass
+ file:(GPBFileDescriptor *)file
+ fields:(GPBMessageFieldDescription *)fieldDescriptions
+ fieldCount:(NSUInteger)fieldCount
+ oneofs:(GPBMessageOneofDescription *)oneofDescriptions
+ oneofCount:(NSUInteger)oneofCount
+ enums:(GPBMessageEnumDescription *)enumDescriptions
+ enumCount:(NSUInteger)enumCount
+ ranges:(const GPBExtensionRange *)ranges
+ rangeCount:(NSUInteger)rangeCount
+ storageSize:(size_t)storageSize
+ wireFormat:(BOOL)wireFormat
+ extraTextFormatInfo:(const char *)extraTextFormatInfo;
+
+- (instancetype)initWithClass:(Class)messageClass
+ file:(GPBFileDescriptor *)file
+ fields:(NSArray *)fields
+ oneofs:(NSArray *)oneofs
+ enums:(NSArray *)enums
+ extensions:(NSArray *)extensions
+ extensionRanges:(const GPBExtensionRange *)ranges
+ extensionRangesCount:(NSUInteger)rangeCount
+ storageSize:(size_t)storage
+ wireFormat:(BOOL)wireFormat;
+
+@end
+
+@interface GPBFileDescriptor ()
+- (instancetype)initWithPackage:(NSString *)package
+ syntax:(GPBFileSyntax)syntax;
+@end
+
+@interface GPBOneofDescriptor () {
+ @package
+ GPBMessageOneofDescription *oneofDescription_;
+ NSArray *fields_;
+
+ SEL caseSel_;
+}
+- (instancetype)initWithOneofDescription:
+ (GPBMessageOneofDescription *)oneofDescription
+ fields:(NSArray *)fields;
+@end
+
+@interface GPBFieldDescriptor () {
+ @package
+ GPBMessageFieldDescription *description_;
+ GPB_UNSAFE_UNRETAINED GPBOneofDescriptor *containingOneof_;
+
+ SEL getSel_;
+ SEL setSel_;
+ SEL hasSel_;
+ SEL setHasSel_;
+}
+
+// Single initializer
+// description has to be long lived, it is held as a raw pointer.
+- (instancetype)initWithFieldDescription:
+ (GPBMessageFieldDescription *)description
+ rootClass:(Class)rootClass
+ syntax:(GPBFileSyntax)syntax;
+@end
+
+@interface GPBEnumDescriptor ()
+// valueDescriptions and extraTextFormatInfo have to be long lived, they are
+// held as raw pointers.
++ (instancetype)
+ allocDescriptorForName:(NSString *)name
+ values:(GPBMessageEnumValueDescription *)valueDescriptions
+ valueCount:(NSUInteger)valueCount
+ enumVerifier:(GPBEnumValidationFunc)enumVerifier;
++ (instancetype)
+ allocDescriptorForName:(NSString *)name
+ values:(GPBMessageEnumValueDescription *)valueDescriptions
+ valueCount:(NSUInteger)valueCount
+ enumVerifier:(GPBEnumValidationFunc)enumVerifier
+ extraTextFormatInfo:(const char *)extraTextFormatInfo;
+
+- (instancetype)initWithName:(NSString *)name
+ values:(GPBMessageEnumValueDescription *)valueDescriptions
+ valueCount:(NSUInteger)valueCount
+ enumVerifier:(GPBEnumValidationFunc)enumVerifier;
+@end
+
+@interface GPBExtensionDescriptor () {
+ @package
+ GPBExtensionDescription *description_;
+}
+
+// description has to be long lived, it is held as a raw pointer.
+- (instancetype)initWithExtensionDescription:
+ (GPBExtensionDescription *)description;
+@end
+
+CF_EXTERN_C_BEGIN
+
+GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) {
+ return (field->description_->flags &
+ (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0;
+}
+
+GPB_INLINE GPBType GPBGetFieldType(GPBFieldDescriptor *field) {
+ return field->description_->type;
+}
+
+GPB_INLINE int32_t GPBFieldHasIndex(GPBFieldDescriptor *field) {
+ return field->description_->hasIndex;
+}
+
+GPB_INLINE uint32_t GPBFieldNumber(GPBFieldDescriptor *field) {
+ return field->description_->number;
+}
+
+uint32_t GPBFieldTag(GPBFieldDescriptor *self);
+
+GPB_INLINE BOOL GPBPreserveUnknownFields(GPBFileSyntax syntax) {
+ return syntax != GPBFileSyntaxProto3;
+}
+
+GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) {
+ return syntax == GPBFileSyntaxProto3;
+}
+
+CF_EXTERN_C_END
diff --git a/objectivec/GPBDictionary.h b/objectivec/GPBDictionary.h
new file mode 100644
index 00000000..72873ad2
--- /dev/null
+++ b/objectivec/GPBDictionary.h
@@ -0,0 +1,2233 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBTypes.h"
+
+// These classes are used for map fields of basic data types. They are used because
+// they perform better than boxing into NSNumbers in NSDictionaries.
+
+// Note: These are not meant to be subclassed.
+
+//%PDDM-EXPAND DECLARE_DICTIONARIES()
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt32 -> UInt32
+
+@interface GPBUInt32UInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32UInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Int32
+
+@interface GPBUInt32Int32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32Int32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32Int32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32Int32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> UInt64
+
+@interface GPBUInt32UInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32UInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Int64
+
+@interface GPBUInt32Int64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32Int64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32Int64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32Int64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Bool
+
+@interface GPBUInt32BoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32BoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32BoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32BoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Float
+
+@interface GPBUInt32FloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32FloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32FloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32FloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Double
+
+@interface GPBUInt32DoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32DoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32DoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint32_t)key value:(double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32DoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Enum
+
+@interface GPBUInt32EnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32EnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32EnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(uint32_t)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(uint32_t)key rawValue:(int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(uint32_t key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(uint32_t)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(uint32_t)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt32 -> Object
+
+@interface GPBUInt32ObjectDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(id)value
+ forKey:(uint32_t)key;
++ (instancetype)dictionaryWithValues:(const id GPB_UNSAFE_UNRETAINED [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt32ObjectDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const id GPB_UNSAFE_UNRETAINED [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (id)valueForKey:(uint32_t)key;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, id value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary;
+
+- (void)setValue:(id)value forKey:(uint32_t)key;
+
+- (void)removeValueForKey:(uint32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> UInt32
+
+@interface GPBInt32UInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32UInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32UInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32UInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Int32
+
+@interface GPBInt32Int32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32Int32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32Int32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32Int32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> UInt64
+
+@interface GPBInt32UInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32UInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32UInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32UInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Int64
+
+@interface GPBInt32Int64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32Int64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32Int64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32Int64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Bool
+
+@interface GPBInt32BoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32BoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32BoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32BoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Float
+
+@interface GPBInt32FloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32FloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32FloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32FloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Double
+
+@interface GPBInt32DoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32DoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32DoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int32_t)key value:(double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32DoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Enum
+
+@interface GPBInt32EnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(int32_t)key;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32EnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32EnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(int32_t)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(int32_t)key rawValue:(int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(int32_t key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(int32_t)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(int32_t)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int32 -> Object
+
+@interface GPBInt32ObjectDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(id)value
+ forKey:(int32_t)key;
++ (instancetype)dictionaryWithValues:(const id GPB_UNSAFE_UNRETAINED [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt32ObjectDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const id GPB_UNSAFE_UNRETAINED [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (id)valueForKey:(int32_t)key;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, id value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary;
+
+- (void)setValue:(id)value forKey:(int32_t)key;
+
+- (void)removeValueForKey:(int32_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> UInt32
+
+@interface GPBUInt64UInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64UInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Int32
+
+@interface GPBUInt64Int32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64Int32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64Int32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64Int32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> UInt64
+
+@interface GPBUInt64UInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64UInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Int64
+
+@interface GPBUInt64Int64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64Int64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64Int64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64Int64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Bool
+
+@interface GPBUInt64BoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64BoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64BoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64BoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Float
+
+@interface GPBUInt64FloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64FloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64FloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64FloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Double
+
+@interface GPBUInt64DoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64DoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64DoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(uint64_t)key value:(double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64DoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Enum
+
+@interface GPBUInt64EnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64EnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64EnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(uint64_t)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(uint64_t)key rawValue:(int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(uint64_t key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(uint64_t)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(uint64_t)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - UInt64 -> Object
+
+@interface GPBUInt64ObjectDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(id)value
+ forKey:(uint64_t)key;
++ (instancetype)dictionaryWithValues:(const id GPB_UNSAFE_UNRETAINED [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBUInt64ObjectDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const id GPB_UNSAFE_UNRETAINED [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (id)valueForKey:(uint64_t)key;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, id value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary;
+
+- (void)setValue:(id)value forKey:(uint64_t)key;
+
+- (void)removeValueForKey:(uint64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> UInt32
+
+@interface GPBInt64UInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64UInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64UInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64UInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Int32
+
+@interface GPBInt64Int32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64Int32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64Int32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64Int32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> UInt64
+
+@interface GPBInt64UInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64UInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64UInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64UInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Int64
+
+@interface GPBInt64Int64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64Int64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64Int64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64Int64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Bool
+
+@interface GPBInt64BoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64BoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64BoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64BoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Float
+
+@interface GPBInt64FloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64FloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64FloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64FloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Double
+
+@interface GPBInt64DoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64DoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64DoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(int64_t)key value:(double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64DoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Enum
+
+@interface GPBInt64EnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(int64_t)key;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64EnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64EnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(int64_t)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(int64_t)key rawValue:(int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(int64_t key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(int64_t)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(int64_t)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Int64 -> Object
+
+@interface GPBInt64ObjectDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(id)value
+ forKey:(int64_t)key;
++ (instancetype)dictionaryWithValues:(const id GPB_UNSAFE_UNRETAINED [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBInt64ObjectDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const id GPB_UNSAFE_UNRETAINED [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (id)valueForKey:(int64_t)key;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, id value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary;
+
+- (void)setValue:(id)value forKey:(int64_t)key;
+
+- (void)removeValueForKey:(int64_t)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> UInt32
+
+@interface GPBBoolUInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolUInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolUInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolUInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Int32
+
+@interface GPBBoolInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> UInt64
+
+@interface GPBBoolUInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolUInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolUInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolUInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Int64
+
+@interface GPBBoolInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Bool
+
+@interface GPBBoolBoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolBoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolBoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolBoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Float
+
+@interface GPBBoolFloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolFloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolFloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolFloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Double
+
+@interface GPBBoolDoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolDoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolDoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(BOOL)key value:(double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolDoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Enum
+
+@interface GPBBoolEnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(BOOL)key;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolEnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolEnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(BOOL)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(BOOL)key rawValue:(int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(BOOL key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBBoolEnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(BOOL)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(BOOL)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - Bool -> Object
+
+@interface GPBBoolObjectDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(id)value
+ forKey:(BOOL)key;
++ (instancetype)dictionaryWithValues:(const id GPB_UNSAFE_UNRETAINED [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBBoolObjectDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const id GPB_UNSAFE_UNRETAINED [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (id)valueForKey:(BOOL)key;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, id value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary;
+
+- (void)setValue:(id)value forKey:(BOOL)key;
+
+- (void)removeValueForKey:(BOOL)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> UInt32
+
+@interface GPBStringUInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringUInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringUInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(uint32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, uint32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringUInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(uint32_t)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Int32
+
+@interface GPBStringInt32Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringInt32Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringInt32Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, int32_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringInt32Dictionary *)otherDictionary;
+
+- (void)setValue:(int32_t)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> UInt64
+
+@interface GPBStringUInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringUInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringUInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(uint64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, uint64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringUInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(uint64_t)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Int64
+
+@interface GPBStringInt64Dictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringInt64Dictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringInt64Dictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(int64_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, int64_t value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringInt64Dictionary *)otherDictionary;
+
+- (void)setValue:(int64_t)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Bool
+
+@interface GPBStringBoolDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringBoolDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringBoolDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(BOOL *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, BOOL value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringBoolDictionary *)otherDictionary;
+
+- (void)setValue:(BOOL)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Float
+
+@interface GPBStringFloatDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringFloatDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringFloatDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(float *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, float value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringFloatDictionary *)otherDictionary;
+
+- (void)setValue:(float)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Double
+
+@interface GPBStringDoubleDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(NSString *)key;
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringDoubleDictionary *)dictionary;
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringDoubleDictionary *)dictionary;
+- (instancetype)initWithCapacity:(NSUInteger)numItems;
+
+- (BOOL)valueForKey:(NSString *)key value:(double *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, double value, BOOL *stop))block;
+
+- (void)addEntriesFromDictionary:(GPBStringDoubleDictionary *)otherDictionary;
+
+- (void)setValue:(double)value forKey:(NSString *)key;
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+#pragma mark - String -> Enum
+
+@interface GPBStringEnumDictionary : NSObject <NSCopying>
+
+@property(nonatomic, readonly) NSUInteger count;
+@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+
++ (instancetype)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(NSString *)key;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count;
++ (instancetype)dictionaryWithDictionary:(GPBStringEnumDictionary *)dictionary;
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const NSString * GPB_UNSAFE_UNRETAINED [])keys
+ count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+- (instancetype)initWithDictionary:(GPBStringEnumDictionary *)dictionary;
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems;
+
+// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+// is not a valid enumerator as defined by validationFunc. If the actual value is
+// desired, use "raw" version of the method.
+
+- (BOOL)valueForKey:(NSString *)key value:(int32_t *)value;
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, int32_t value, BOOL *stop))block;
+
+// These methods bypass the validationFunc to provide access to values that were not
+// known at the time the binary was compiled.
+
+- (BOOL)valueForKey:(NSString *)key rawValue:(int32_t *)rawValue;
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(NSString *key, int32_t rawValue, BOOL *stop))block;
+
+- (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary;
+
+// If value is not a valid enumerator as defined by validationFunc, these
+// methods will assert in debug, and will log in release and assign the value
+// to the default value. Use the rawValue methods below to assign non enumerator
+// values.
+
+- (void)setValue:(int32_t)value forKey:(NSString *)key;
+
+// This method bypass the validationFunc to provide setting of values that were not
+// known at the time the binary was compiled.
+- (void)setRawValue:(int32_t)rawValue forKey:(NSString *)key;
+
+// No validation applies to these methods.
+
+- (void)removeValueForKey:(NSString *)aKey;
+- (void)removeAll;
+
+@end
+
+//%PDDM-EXPAND-END DECLARE_DICTIONARIES()
+
+//%PDDM-DEFINE DECLARE_DICTIONARIES()
+//%DICTIONARY_INTERFACES_FOR_POD_KEY(UInt32, uint32_t)
+//%DICTIONARY_INTERFACES_FOR_POD_KEY(Int32, int32_t)
+//%DICTIONARY_INTERFACES_FOR_POD_KEY(UInt64, uint64_t)
+//%DICTIONARY_INTERFACES_FOR_POD_KEY(Int64, int64_t)
+//%DICTIONARY_INTERFACES_FOR_POD_KEY(Bool, BOOL)
+//%DICTIONARY_POD_INTERFACES_FOR_KEY(String, NSString, *, OBJECT)
+//%PDDM-DEFINE DICTIONARY_INTERFACES_FOR_POD_KEY(KEY_NAME, KEY_TYPE)
+//%DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, , POD)
+//%DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, Object, id)
+//%PDDM-DEFINE DICTIONARY_POD_INTERFACES_FOR_KEY(KEY_NAME, KEY_TYPE, KisP, KHELPER)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, UInt32, uint32_t)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Int32, int32_t)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, UInt64, uint64_t)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Int64, int64_t)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Bool, BOOL)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Float, float)
+//%DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Double, double)
+//%DICTIONARY_KEY_TO_ENUM_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, Enum, int32_t)
+//%PDDM-DEFINE DICTIONARY_KEY_TO_POD_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, POD)
+//%PDDM-DEFINE DICTIONARY_POD_KEY_TO_OBJECT_INTERFACE(KEY_NAME, KEY_TYPE, VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, , POD, VALUE_NAME, VALUE_TYPE, OBJECT)
+//%PDDM-DEFINE VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_TYPE)
+//%- (BOOL)valueForKey:(KEY_TYPE)key value:(VALUE_TYPE *)value;
+//%PDDM-DEFINE VALUE_FOR_KEY_OBJECT(KEY_TYPE, VALUE_TYPE)
+//%- (VALUE_TYPE)valueForKey:(KEY_TYPE)key;
+//%PDDM-DEFINE VALUE_FOR_KEY_Enum(KEY_TYPE, VALUE_TYPE)
+//%VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_TYPE)
+//%PDDM-DEFINE ARRAY_ARG_MODIFIERPOD()
+// Nothing
+//%PDDM-DEFINE ARRAY_ARG_MODIFIEREnum()
+// Nothing
+//%PDDM-DEFINE ARRAY_ARG_MODIFIEROBJECT()
+//%GPB_UNSAFE_UNRETAINED ##
+//%PDDM-DEFINE DICTIONARY_COMMON_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary : NSObject <NSCopying>
+//%
+//%@property(nonatomic, readonly) NSUInteger count;
+//%
+//%+ (instancetype)dictionary;
+//%+ (instancetype)dictionaryWithValue:(VALUE_TYPE)value
+//% forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%+ (instancetype)dictionaryWithValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])values
+//% forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
+//% count:(NSUInteger)count;
+//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems;
+//%
+//%- (instancetype)initWithValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])values
+//% forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
+//% count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%- (instancetype)initWithCapacity:(NSUInteger)numItems;
+//%
+//%DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER)
+//%
+//%- (void)addEntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary;
+//%
+//%DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER)
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_INTERFACE(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_KEY_TO_ENUM_INTERFACE2(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, Enum)
+//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_INTERFACE2(KEY_NAME, KEY_TYPE, KisP, KHELPER, VALUE_NAME, VALUE_TYPE, VHELPER)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary : NSObject <NSCopying>
+//%
+//%@property(nonatomic, readonly) NSUInteger count;
+//%@property(nonatomic, readonly) GPBEnumValidationFunc validationFunc;
+//%
+//%+ (instancetype)dictionary;
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func;
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+//% rawValue:(VALUE_TYPE)rawValue
+//% forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+//% rawValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])values
+//% forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
+//% count:(NSUInteger)count;
+//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+//% capacity:(NSUInteger)numItems;
+//%
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func;
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+//% rawValues:(const VALUE_TYPE ARRAY_ARG_MODIFIER##VHELPER()[])values
+//% forKeys:(const KEY_TYPE##KisP$S##KisP ARRAY_ARG_MODIFIER##KHELPER()[])keys
+//% count:(NSUInteger)count NS_DESIGNATED_INITIALIZER;
+//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary;
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+//% capacity:(NSUInteger)numItems;
+//%
+//%// These will return kGPBUnrecognizedEnumeratorValue if the value for the key
+//%// is not a valid enumerator as defined by validationFunc. If the actual value is
+//%// desired, use "raw" version of the method.
+//%
+//%DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER)
+//%
+//%// These methods bypass the validationFunc to provide access to values that were not
+//%// known at the time the binary was compiled.
+//%
+//%- (BOOL)valueForKey:(KEY_TYPE##KisP$S##KisP)key rawValue:(VALUE_TYPE *)rawValue;
+//%
+//%- (void)enumerateKeysAndRawValuesUsingBlock:
+//% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE rawValue, BOOL *stop))block;
+//%
+//%- (void)addRawEntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary;
+//%
+//%// If value is not a valid enumerator as defined by validationFunc, these
+//%// methods will assert in debug, and will log in release and assign the value
+//%// to the default value. Use the rawValue methods below to assign non enumerator
+//%// values.
+//%
+//%DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER)
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE DICTIONARY_IMMUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER)
+//%VALUE_FOR_KEY_##VHELPER(KEY_TYPE##KisP$S##KisP, VALUE_TYPE)
+//%
+//%- (void)enumerateKeysAndValuesUsingBlock:
+//% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE value, BOOL *stop))block;
+
+//%PDDM-DEFINE DICTIONARY_MUTABLE_INTERFACE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, VHELPER)
+//%- (void)setValue:(VALUE_TYPE)value forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%DICTIONARY_EXTRA_MUTABLE_METHODS_##VHELPER(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
+//%- (void)removeValueForKey:(KEY_TYPE##KisP$S##KisP)aKey;
+//%- (void)removeAll;
+
+//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_POD(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
+// Empty
+//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_OBJECT(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
+// Empty
+//%PDDM-DEFINE DICTIONARY_EXTRA_MUTABLE_METHODS_Enum(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE)
+//%
+//%// This method bypass the validationFunc to provide setting of values that were not
+//%// known at the time the binary was compiled.
+//%- (void)setRawValue:(VALUE_TYPE)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%
+//%// No validation applies to these methods.
+//%
diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m
new file mode 100644
index 00000000..de7347e8
--- /dev/null
+++ b/objectivec/GPBDictionary.m
@@ -0,0 +1,12627 @@
+// 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 "GPBDictionary_PackagePrivate.h"
+
+#import "GPBCodedInputStream_PackagePrivate.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+// ------------------------------ NOTE ------------------------------
+// At the moment, this is all using NSNumbers in NSDictionaries under
+// the hood, but it is all hidden so we can come back and optimize
+// with direct CFDictionary usage later. The reason that wasn't
+// done yet is needing to support 32bit iOS builds. Otherwise
+// it would be pretty simple to store all this data in CFDictionaries
+// directly.
+// ------------------------------------------------------------------
+
+#define kMapKeyFieldNumber 1
+#define kMapValueFieldNumber 2
+
+static BOOL DictDefault_IsValidValue(int32_t value) {
+ // Anything but the bad value marker is allowed.
+ return (value != kGPBUnrecognizedEnumeratorValue);
+}
+
+//%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBTYPE_NAME1, GPBTYPE_NAME2)
+//%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) {
+//% NSCAssert((wireType == GPBType##GPBTYPE_NAME1) || (wireType == GPBType##GPBTYPE_NAME2),
+//% @"bad type: %d", wireType);
+//% if (wireType == GPBType##GPBTYPE_NAME1) {
+//% return GPBCompute##GPBTYPE_NAME1##Size(fieldNum, value);
+//% } else { // wireType == GPBType##GPBTYPE_NAME2
+//% return GPBCompute##GPBTYPE_NAME2##Size(fieldNum, value);
+//% }
+//%}
+//%
+//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) {
+//% NSCAssert((wireType == GPBType##GPBTYPE_NAME1) || (wireType == GPBType##GPBTYPE_NAME2),
+//% @"bad type: %d", wireType);
+//% if (wireType == GPBType##GPBTYPE_NAME1) {
+//% [stream write##GPBTYPE_NAME1##:fieldNum value:value];
+//% } else { // wireType == GPBType##GPBTYPE_NAME2
+//% [stream write##GPBTYPE_NAME2##:fieldNum value:value];
+//% }
+//%}
+//%
+//%PDDM-DEFINE SERIALIZE_SUPPORT_3_TYPE(VALUE_NAME, VALUE_TYPE, GPBTYPE_NAME1, GPBTYPE_NAME2, GPBTYPE_NAME3)
+//%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) {
+//% NSCAssert((wireType == GPBType##GPBTYPE_NAME1) || (wireType == GPBType##GPBTYPE_NAME2) || (wireType == GPBType##GPBTYPE_NAME3),
+//% @"bad type: %d", wireType);
+//% if (wireType == GPBType##GPBTYPE_NAME1) {
+//% return GPBCompute##GPBTYPE_NAME1##Size(fieldNum, value);
+//% } else if (wireType == GPBType##GPBTYPE_NAME2) {
+//% return GPBCompute##GPBTYPE_NAME2##Size(fieldNum, value);
+//% } else { // wireType == GPBType##GPBTYPE_NAME3
+//% return GPBCompute##GPBTYPE_NAME3##Size(fieldNum, value);
+//% }
+//%}
+//%
+//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE value, uint32_t fieldNum, GPBType wireType) {
+//% NSCAssert((wireType == GPBType##GPBTYPE_NAME1) || (wireType == GPBType##GPBTYPE_NAME2) || (wireType == GPBType##GPBTYPE_NAME3),
+//% @"bad type: %d", wireType);
+//% if (wireType == GPBType##GPBTYPE_NAME1) {
+//% [stream write##GPBTYPE_NAME1##:fieldNum value:value];
+//% } else if (wireType == GPBType##GPBTYPE_NAME2) {
+//% [stream write##GPBTYPE_NAME2##:fieldNum value:value];
+//% } else { // wireType == GPBType##GPBTYPE_NAME3
+//% [stream write##GPBTYPE_NAME3##:fieldNum value:value];
+//% }
+//%}
+//%
+//%PDDM-DEFINE SIMPLE_SERIALIZE_SUPPORT(VALUE_NAME, VALUE_TYPE, VisP)
+//%GPB_INLINE size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBType wireType) {
+//% NSCAssert(wireType == GPBType##VALUE_NAME, @"bad type: %d", wireType);
+//% return GPBCompute##VALUE_NAME##Size(fieldNum, value);
+//%}
+//%
+//%GPB_INLINE void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBType wireType) {
+//% NSCAssert(wireType == GPBType##VALUE_NAME, @"bad type: %d", wireType);
+//% [stream write##VALUE_NAME##:fieldNum value:value];
+//%}
+//%
+//%PDDM-DEFINE SERIALIZE_SUPPORT_HELPERS()
+//%SERIALIZE_SUPPORT_3_TYPE(Int32, int32_t, Int32, SInt32, SFixed32)
+//%SERIALIZE_SUPPORT_2_TYPE(UInt32, uint32_t, UInt32, Fixed32)
+//%SERIALIZE_SUPPORT_3_TYPE(Int64, int64_t, Int64, SInt64, SFixed64)
+//%SERIALIZE_SUPPORT_2_TYPE(UInt64, uint64_t, UInt64, Fixed64)
+//%SIMPLE_SERIALIZE_SUPPORT(Bool, BOOL, )
+//%SIMPLE_SERIALIZE_SUPPORT(Enum, int32_t, )
+//%SIMPLE_SERIALIZE_SUPPORT(Float, float, )
+//%SIMPLE_SERIALIZE_SUPPORT(Double, double, )
+//%SIMPLE_SERIALIZE_SUPPORT(String, NSString, *)
+//%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Data)
+//%PDDM-EXPAND SERIALIZE_SUPPORT_HELPERS()
+// This block of code is generated, do not edit it directly.
+
+GPB_INLINE size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert((wireType == GPBTypeInt32) || (wireType == GPBTypeSInt32) || (wireType == GPBTypeSFixed32),
+ @"bad type: %d", wireType);
+ if (wireType == GPBTypeInt32) {
+ return GPBComputeInt32Size(fieldNum, value);
+ } else if (wireType == GPBTypeSInt32) {
+ return GPBComputeSInt32Size(fieldNum, value);
+ } else { // wireType == GPBTypeSFixed32
+ return GPBComputeSFixed32Size(fieldNum, value);
+ }
+}
+
+GPB_INLINE void WriteDictInt32Field(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert((wireType == GPBTypeInt32) || (wireType == GPBTypeSInt32) || (wireType == GPBTypeSFixed32),
+ @"bad type: %d", wireType);
+ if (wireType == GPBTypeInt32) {
+ [stream writeInt32:fieldNum value:value];
+ } else if (wireType == GPBTypeSInt32) {
+ [stream writeSInt32:fieldNum value:value];
+ } else { // wireType == GPBTypeSFixed32
+ [stream writeSFixed32:fieldNum value:value];
+ }
+}
+
+GPB_INLINE size_t ComputeDictUInt32FieldSize(uint32_t value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert((wireType == GPBTypeUInt32) || (wireType == GPBTypeFixed32),
+ @"bad type: %d", wireType);
+ if (wireType == GPBTypeUInt32) {
+ return GPBComputeUInt32Size(fieldNum, value);
+ } else { // wireType == GPBTypeFixed32
+ return GPBComputeFixed32Size(fieldNum, value);
+ }
+}
+
+GPB_INLINE void WriteDictUInt32Field(GPBCodedOutputStream *stream, uint32_t value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert((wireType == GPBTypeUInt32) || (wireType == GPBTypeFixed32),
+ @"bad type: %d", wireType);
+ if (wireType == GPBTypeUInt32) {
+ [stream writeUInt32:fieldNum value:value];
+ } else { // wireType == GPBTypeFixed32
+ [stream writeFixed32:fieldNum value:value];
+ }
+}
+
+GPB_INLINE size_t ComputeDictInt64FieldSize(int64_t value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert((wireType == GPBTypeInt64) || (wireType == GPBTypeSInt64) || (wireType == GPBTypeSFixed64),
+ @"bad type: %d", wireType);
+ if (wireType == GPBTypeInt64) {
+ return GPBComputeInt64Size(fieldNum, value);
+ } else if (wireType == GPBTypeSInt64) {
+ return GPBComputeSInt64Size(fieldNum, value);
+ } else { // wireType == GPBTypeSFixed64
+ return GPBComputeSFixed64Size(fieldNum, value);
+ }
+}
+
+GPB_INLINE void WriteDictInt64Field(GPBCodedOutputStream *stream, int64_t value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert((wireType == GPBTypeInt64) || (wireType == GPBTypeSInt64) || (wireType == GPBTypeSFixed64),
+ @"bad type: %d", wireType);
+ if (wireType == GPBTypeInt64) {
+ [stream writeInt64:fieldNum value:value];
+ } else if (wireType == GPBTypeSInt64) {
+ [stream writeSInt64:fieldNum value:value];
+ } else { // wireType == GPBTypeSFixed64
+ [stream writeSFixed64:fieldNum value:value];
+ }
+}
+
+GPB_INLINE size_t ComputeDictUInt64FieldSize(uint64_t value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert((wireType == GPBTypeUInt64) || (wireType == GPBTypeFixed64),
+ @"bad type: %d", wireType);
+ if (wireType == GPBTypeUInt64) {
+ return GPBComputeUInt64Size(fieldNum, value);
+ } else { // wireType == GPBTypeFixed64
+ return GPBComputeFixed64Size(fieldNum, value);
+ }
+}
+
+GPB_INLINE void WriteDictUInt64Field(GPBCodedOutputStream *stream, uint64_t value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert((wireType == GPBTypeUInt64) || (wireType == GPBTypeFixed64),
+ @"bad type: %d", wireType);
+ if (wireType == GPBTypeUInt64) {
+ [stream writeUInt64:fieldNum value:value];
+ } else { // wireType == GPBTypeFixed64
+ [stream writeFixed64:fieldNum value:value];
+ }
+}
+
+GPB_INLINE size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert(wireType == GPBTypeBool, @"bad type: %d", wireType);
+ return GPBComputeBoolSize(fieldNum, value);
+}
+
+GPB_INLINE void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert(wireType == GPBTypeBool, @"bad type: %d", wireType);
+ [stream writeBool:fieldNum value:value];
+}
+
+GPB_INLINE size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert(wireType == GPBTypeEnum, @"bad type: %d", wireType);
+ return GPBComputeEnumSize(fieldNum, value);
+}
+
+GPB_INLINE void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert(wireType == GPBTypeEnum, @"bad type: %d", wireType);
+ [stream writeEnum:fieldNum value:value];
+}
+
+GPB_INLINE size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert(wireType == GPBTypeFloat, @"bad type: %d", wireType);
+ return GPBComputeFloatSize(fieldNum, value);
+}
+
+GPB_INLINE void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert(wireType == GPBTypeFloat, @"bad type: %d", wireType);
+ [stream writeFloat:fieldNum value:value];
+}
+
+GPB_INLINE size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert(wireType == GPBTypeDouble, @"bad type: %d", wireType);
+ return GPBComputeDoubleSize(fieldNum, value);
+}
+
+GPB_INLINE void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert(wireType == GPBTypeDouble, @"bad type: %d", wireType);
+ [stream writeDouble:fieldNum value:value];
+}
+
+GPB_INLINE size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert(wireType == GPBTypeString, @"bad type: %d", wireType);
+ return GPBComputeStringSize(fieldNum, value);
+}
+
+GPB_INLINE void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert(wireType == GPBTypeString, @"bad type: %d", wireType);
+ [stream writeString:fieldNum value:value];
+}
+
+GPB_INLINE size_t ComputeDictObjectFieldSize(id value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert((wireType == GPBTypeMessage) || (wireType == GPBTypeString) || (wireType == GPBTypeData),
+ @"bad type: %d", wireType);
+ if (wireType == GPBTypeMessage) {
+ return GPBComputeMessageSize(fieldNum, value);
+ } else if (wireType == GPBTypeString) {
+ return GPBComputeStringSize(fieldNum, value);
+ } else { // wireType == GPBTypeData
+ return GPBComputeDataSize(fieldNum, value);
+ }
+}
+
+GPB_INLINE void WriteDictObjectField(GPBCodedOutputStream *stream, id value, uint32_t fieldNum, GPBType wireType) {
+ NSCAssert((wireType == GPBTypeMessage) || (wireType == GPBTypeString) || (wireType == GPBTypeData),
+ @"bad type: %d", wireType);
+ if (wireType == GPBTypeMessage) {
+ [stream writeMessage:fieldNum value:value];
+ } else if (wireType == GPBTypeString) {
+ [stream writeString:fieldNum value:value];
+ } else { // wireType == GPBTypeData
+ [stream writeData:fieldNum value:value];
+ }
+}
+
+//%PDDM-EXPAND-END SERIALIZE_SUPPORT_HELPERS()
+
+size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) {
+ NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type");
+ GPBType mapValueType = GPBGetFieldType(field);
+ __block size_t result = 0;
+ [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = GPBComputeStringSize(kMapKeyFieldNumber, key);
+ msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * dict.count;
+ return result;
+}
+
+void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream,
+ NSDictionary *dict,
+ GPBFieldDescriptor *field) {
+ NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type");
+ GPBType mapValueType = GPBGetFieldType(field);
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id obj, BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = GPBComputeStringSize(kMapKeyFieldNumber, key);
+ msgSize += ComputeDictObjectFieldSize(obj, kMapValueFieldNumber, mapValueType);
+
+ // Write the size and fields.
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ [outputStream writeString:kMapValueFieldNumber value:obj];
+ WriteDictObjectField(outputStream, obj, kMapValueFieldNumber, mapValueType);
+ }];
+}
+
+BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) {
+ NSCAssert(field.mapKeyType == GPBTypeString, @"Unexpected key type");
+ NSCAssert(GPBGetFieldType(field) == GPBTypeMessage, @"Unexpected value type");
+ for (GPBMessage *msg in [dict objectEnumerator]) {
+ if (!msg.initialized) {
+ return NO;
+ }
+ }
+ return YES;
+}
+
+// Note: if the type is an object, it the retain pass back to the caller.
+static void ReadValue(GPBCodedInputStream *stream,
+ GPBValue *valueToFill,
+ GPBType type,
+ GPBExtensionRegistry *registry,
+ GPBFieldDescriptor *field) {
+ switch (type) {
+ case GPBTypeBool:
+ valueToFill->valueBool = GPBCodedInputStreamReadBool(&stream->state_);
+ break;
+ case GPBTypeFixed32:
+ valueToFill->valueUInt32 = GPBCodedInputStreamReadFixed32(&stream->state_);
+ break;
+ case GPBTypeSFixed32:
+ valueToFill->valueInt32 = GPBCodedInputStreamReadSFixed32(&stream->state_);
+ break;
+ case GPBTypeFloat:
+ valueToFill->valueFloat = GPBCodedInputStreamReadFloat(&stream->state_);
+ break;
+ case GPBTypeFixed64:
+ valueToFill->valueUInt64 = GPBCodedInputStreamReadFixed64(&stream->state_);
+ break;
+ case GPBTypeSFixed64:
+ valueToFill->valueInt64 = GPBCodedInputStreamReadSFixed64(&stream->state_);
+ break;
+ case GPBTypeDouble:
+ valueToFill->valueDouble = GPBCodedInputStreamReadDouble(&stream->state_);
+ break;
+ case GPBTypeInt32:
+ valueToFill->valueInt32 = GPBCodedInputStreamReadInt32(&stream->state_);
+ break;
+ case GPBTypeInt64:
+ valueToFill->valueInt64 = GPBCodedInputStreamReadInt32(&stream->state_);
+ break;
+ case GPBTypeSInt32:
+ valueToFill->valueInt32 = GPBCodedInputStreamReadSInt32(&stream->state_);
+ break;
+ case GPBTypeSInt64:
+ valueToFill->valueInt64 = GPBCodedInputStreamReadSInt64(&stream->state_);
+ break;
+ case GPBTypeUInt32:
+ valueToFill->valueUInt32 = GPBCodedInputStreamReadUInt32(&stream->state_);
+ break;
+ case GPBTypeUInt64:
+ valueToFill->valueUInt64 = GPBCodedInputStreamReadUInt64(&stream->state_);
+ break;
+ case GPBTypeData:
+ [valueToFill->valueData release];
+ valueToFill->valueData = GPBCodedInputStreamReadRetainedData(&stream->state_);
+ break;
+ case GPBTypeString:
+ [valueToFill->valueString release];
+ valueToFill->valueString = GPBCodedInputStreamReadRetainedString(&stream->state_);
+ break;
+ case GPBTypeMessage: {
+ GPBMessage *message = [[field.msgClass alloc] init];
+ [stream readMessage:message extensionRegistry:registry];
+ [valueToFill->valueMessage release];
+ valueToFill->valueMessage = message;
+ break;
+ }
+ case GPBTypeGroup:
+ NSCAssert(NO, @"Can't happen");
+ break;
+ case GPBTypeEnum:
+ valueToFill->valueEnum = GPBCodedInputStreamReadEnum(&stream->state_);
+ break;
+ }
+}
+
+void GPBDictionaryReadEntry(id mapDictionary,
+ GPBCodedInputStream *stream,
+ GPBExtensionRegistry *registry,
+ GPBFieldDescriptor *field,
+ GPBMessage *parentMessage) {
+ GPBType keyType = field.mapKeyType;
+ GPBType valueType = GPBGetFieldType(field);
+
+ GPBValue key;
+ GPBValue value;
+ // Zero them (but pick up any enum default for proto2).
+ key.valueString = value.valueString = nil;
+ if (valueType == GPBTypeEnum) {
+ value = field.defaultValue;
+ }
+
+ GPBCodedInputStreamState *state = &stream->state_;
+ uint32_t keyTag =
+ GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyType, NO));
+ uint32_t valueTag =
+ GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueType, NO));
+
+ BOOL hitError = NO;
+ while (YES) {
+ uint32_t tag = GPBCodedInputStreamReadTag(state);
+ if (tag == keyTag) {
+ ReadValue(stream, &key, keyType, registry, field);
+ } else if (tag == valueTag) {
+ ReadValue(stream, &value, valueType, registry, field);
+ } else if (tag == 0) {
+ // zero signals EOF / limit reached
+ break;
+ } else { // Unknown
+ if (![stream skipField:tag]){
+ hitError = YES;
+ break;
+ }
+ }
+ }
+
+ if (!hitError) {
+ // Handle the special defaults and/or missing key/value.
+ if ((keyType == GPBTypeString) && (key.valueString == nil)) {
+ key.valueString = [@"" retain];
+ }
+ if (GPBTypeIsObject(valueType) && value.valueString == nil) {
+ switch (valueType) {
+ case GPBTypeString:
+ value.valueString = [@"" retain];
+ break;
+ case GPBTypeData:
+ value.valueData = [GPBEmptyNSData() retain];
+ break;
+ case GPBTypeMessage: {
+ value.valueMessage = [[field.msgClass alloc] init];
+ break;
+ }
+ default:
+ // Nothing
+ break;
+ }
+ }
+
+ if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) {
+ // mapDictionary is an NSMutableDictionary
+ [mapDictionary setObject:value.valueString forKey:key.valueString];
+ } else {
+ if (valueType == GPBTypeEnum) {
+ if (GPBHasPreservingUnknownEnumSemantics([parentMessage descriptor].file.syntax) ||
+ [field isValidEnumValue:value.valueEnum]) {
+ [mapDictionary setGPBValue:&value forGPBValueKey:&key];
+ } else {
+ NSData *data = [mapDictionary serializedDataForUnknownValue:value.valueEnum
+ forKey:&key
+ keyType:keyType];
+ [parentMessage addUnknownMapEntry:GPBFieldNumber(field) value:data];
+ }
+ } else {
+ [mapDictionary setGPBValue:&value forGPBValueKey:&key];
+ }
+ }
+ }
+
+ if (GPBTypeIsObject(keyType)) [key.valueString release];
+ if (GPBTypeIsObject(valueType)) [value.valueString release];
+}
+
+//
+// Macros for the common basic cases.
+//
+
+//%PDDM-DEFINE DICTIONARY_IMPL_FOR_POD_KEY(KEY_NAME, KEY_TYPE)
+//%DICTIONARY_POD_IMPL_FOR_KEY(KEY_NAME, KEY_TYPE, , POD)
+//%DICTIONARY_POD_KEY_TO_OBJECT_IMPL(KEY_NAME, KEY_TYPE, Object, id)
+
+//%PDDM-DEFINE DICTIONARY_POD_IMPL_FOR_KEY(KEY_NAME, KEY_TYPE, KisP, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, UInt32, uint32_t, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Int32, int32_t, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, UInt64, uint64_t, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Int64, int64_t, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Bool, BOOL, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Float, float, KHELPER)
+//%DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, Double, double, KHELPER)
+//%DICTIONARY_KEY_TO_ENUM_IMPL(KEY_NAME, KEY_TYPE, KisP, Enum, int32_t, KHELPER)
+
+//%PDDM-DEFINE DICTIONARY_KEY_TO_POD_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER)
+//%DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, POD)
+
+//%PDDM-DEFINE DICTIONARY_POD_KEY_TO_OBJECT_IMPL(KEY_NAME, KEY_TYPE, VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, , VALUE_NAME, VALUE_TYPE, POD, OBJECT)
+
+//%PDDM-DEFINE DICTIONARY_COMMON_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##Dictionary {
+//% @package
+//% NSMutableDictionary *_dictionary;
+//%}
+//%
+//%+ (instancetype)dictionary {
+//% return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValue:(VALUE_TYPE)value
+//% forKey:(KEY_TYPE##KisP$S##KisP)key {
+//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//% // on to get the type correct.
+//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithValues:&value
+//% KEY_NAME$S VALUE_NAME$S forKeys:&key
+//% KEY_NAME$S VALUE_NAME$S count:1] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValues:(const VALUE_TYPE [])values
+//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//% count:(NSUInteger)count {
+//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//% // on to get the type correct.
+//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithValues:values
+//% KEY_NAME$S VALUE_NAME$S forKeys:keys
+//% KEY_NAME$S VALUE_NAME$S count:count] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary {
+//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//% // on to get the type correct.
+//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+//% return [[[self alloc] initWithCapacity:numItems] autorelease];
+//%}
+//%
+//%- (instancetype)init {
+//% return [self initWithValues:NULL forKeys:NULL count:0];
+//%}
+//%
+//%- (instancetype)initWithValues:(const VALUE_TYPE [])values
+//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//% count:(NSUInteger)count {
+//% self = [super init];
+//% if (self) {
+//% _dictionary = [[NSMutableDictionary alloc] init];
+//% if (count && values && keys) {
+//% for (NSUInteger i = 0; i < count; ++i) {
+//% [_dictionary setObject:WRAPPED##VHELPER(values[i]) forKey:WRAPPED##KHELPER(keys[i])];
+//% }
+//% }
+//% }
+//% return self;
+//%}
+//%
+//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary {
+//% self = [self initWithValues:NULL forKeys:NULL count:0];
+//% if (self) {
+//% if (dictionary) {
+//% [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+//% }
+//% }
+//% return self;
+//%}
+//%
+//%- (instancetype)initWithCapacity:(NSUInteger)numItems {
+//% #pragma unused(numItems)
+//% return [self initWithValues:NULL forKeys:NULL count:0];
+//%}
+//%
+//%DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, )
+//%
+//%VALUE_FOR_KEY_##VHELPER(KEY_TYPE##KisP$S##KisP, VALUE_NAME, VALUE_TYPE, KHELPER)
+//%
+//%DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, )
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_IMPL(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER)
+//%DICTIONARY_KEY_TO_ENUM_IMPL2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, POD)
+//%PDDM-DEFINE DICTIONARY_KEY_TO_ENUM_IMPL2(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##Dictionary {
+//% @package
+//% NSMutableDictionary *_dictionary;
+//% GPBEnumValidationFunc _validationFunc;
+//%}
+//%
+//%@synthesize validationFunc = _validationFunc;
+//%
+//%+ (instancetype)dictionary {
+//% return [[[self alloc] initWithValidationFunction:NULL
+//% rawValues:NULL
+//% forKeys:NULL
+//% count:0] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+//% return [[[self alloc] initWithValidationFunction:func
+//% rawValues:NULL
+//% forKeys:NULL
+//% count:0] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+//% rawValue:(VALUE_TYPE)rawValue
+//% forKey:(KEY_TYPE##KisP$S##KisP)key {
+//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//% // on to get the type correct.
+//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithValidationFunction:func
+//% KEY_NAME$S VALUE_NAME$S rawValues:&rawValue
+//% KEY_NAME$S VALUE_NAME$S forKeys:&key
+//% KEY_NAME$S VALUE_NAME$S count:1] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+//% rawValues:(const VALUE_TYPE [])rawValues
+//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//% count:(NSUInteger)count {
+//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//% // on to get the type correct.
+//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithValidationFunction:func
+//% KEY_NAME$S VALUE_NAME$S rawValues:rawValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:keys
+//% KEY_NAME$S VALUE_NAME$S count:count] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary {
+//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//% // on to get the type correct.
+//% return [[(GPB##KEY_NAME##VALUE_NAME##Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+//% capacity:(NSUInteger)numItems {
+//% return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+//%}
+//%
+//%- (instancetype)init {
+//% return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+//%}
+//%
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+//% return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+//%}
+//%
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+//% rawValues:(const VALUE_TYPE [])rawValues
+//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//% count:(NSUInteger)count {
+//% self = [super init];
+//% if (self) {
+//% _dictionary = [[NSMutableDictionary alloc] init];
+//% _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+//% if (count && rawValues && keys) {
+//% for (NSUInteger i = 0; i < count; ++i) {
+//% [_dictionary setObject:WRAPPED##VHELPER(rawValues[i]) forKey:WRAPPED##KHELPER(keys[i])];
+//% }
+//% }
+//% }
+//% return self;
+//%}
+//%
+//%- (instancetype)initWithDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)dictionary {
+//% self = [self initWithValidationFunction:dictionary.validationFunc
+//% rawValues:NULL
+//% forKeys:NULL
+//% count:0];
+//% if (self) {
+//% if (dictionary) {
+//% [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+//% }
+//% }
+//% return self;
+//%}
+//%
+//%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+//% capacity:(NSUInteger)numItems {
+//% #pragma unused(numItems)
+//% return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+//%}
+//%
+//%DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, Raw)
+//%
+//%- (BOOL)valueForKey:(KEY_TYPE##KisP$S##KisP)key value:(VALUE_TYPE *)value {
+//% NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)];
+//% if (wrapped && value) {
+//% VALUE_TYPE result = UNWRAP##VALUE_NAME(wrapped);
+//% if (!_validationFunc(result)) {
+//% result = kGPBUnrecognizedEnumeratorValue;
+//% }
+//% *value = result;
+//% }
+//% return (wrapped != NULL);
+//%}
+//%
+//%- (BOOL)valueForKey:(KEY_TYPE##KisP$S##KisP)key rawValue:(VALUE_TYPE *)rawValue {
+//% NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)];
+//% if (wrapped && rawValue) {
+//% *rawValue = UNWRAP##VALUE_NAME(wrapped);
+//% }
+//% return (wrapped != NULL);
+//%}
+//%
+//%- (void)enumerateKeysAndValuesUsingBlock:
+//% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE value, BOOL *stop))block {
+//% GPBEnumValidationFunc func = _validationFunc;
+//% [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
+//% ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue,
+//% BOOL *stop) {
+//% VALUE_TYPE unwrapped = UNWRAP##VALUE_NAME(aValue);
+//% if (!func(unwrapped)) {
+//% unwrapped = kGPBUnrecognizedEnumeratorValue;
+//% }
+//% block(UNWRAP##KEY_NAME(aKey), unwrapped, stop);
+//% }];
+//%}
+//%
+//%DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, Raw)
+//%
+//%- (void)setValue:(VALUE_TYPE)value forKey:(KEY_TYPE##KisP$S##KisP)key {
+//% if (!_validationFunc(value)) {
+//% [NSException raise:NSInvalidArgumentException
+//% format:@"GPB##KEY_NAME##VALUE_NAME##Dictionary: Attempt to set an unknown enum value (%d)",
+//% value];
+//% }
+//%
+//% [_dictionary setObject:WRAPPED##VHELPER(value) forKey:WRAPPED##KHELPER(key)];
+//%}
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE DICTIONARY_IMMUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, ACCESSOR_NAME)
+//%- (void)dealloc {
+//% [_dictionary release];
+//% [super dealloc];
+//%}
+//%
+//%- (instancetype)copyWithZone:(NSZone *)zone {
+//% return [[GPB##KEY_NAME##VALUE_NAME##Dictionary allocWithZone:zone] initWithDictionary:self];
+//%}
+//%
+//%- (BOOL)isEqual:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)other {
+//% if (self == other) {
+//% return YES;
+//% }
+//% if (![other isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]) {
+//% return NO;
+//% }
+//% return [_dictionary isEqual:other->_dictionary];
+//%}
+//%
+//%- (NSUInteger)hash {
+//% return _dictionary.count;
+//%}
+//%
+//%- (NSString *)description {
+//% return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+//%}
+//%
+//%- (NSUInteger)count {
+//% return _dictionary.count;
+//%}
+//%
+//%- (void)enumerateKeysAnd##ACCESSOR_NAME##ValuesUsingBlock:
+//% (void (^)(KEY_TYPE KisP##key, VALUE_TYPE value, BOOL *stop))block {
+//% [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
+//% ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue,
+//% BOOL *stop) {
+//% block(UNWRAP##KEY_NAME(aKey), UNWRAP##VALUE_NAME(aValue), stop);
+//% }];
+//%}
+//%
+//%EXTRA_METHODS_##VHELPER(KEY_NAME, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+//% NSUInteger count = _dictionary.count;
+//% if (count == 0) {
+//% return 0;
+//% }
+//%
+//% GPBType valueType = GPBGetFieldType(field);
+//% GPBType keyType = field.mapKeyType;
+//% __block size_t result = 0;
+//% [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
+//% ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue,
+//% BOOL *stop) {
+//% #pragma unused(stop)
+//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyType);
+//% msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueType);
+//% result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+//% }];
+//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+//% result += tagSize * count;
+//% return result;
+//%}
+//%
+//%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+//% asField:(GPBFieldDescriptor *)field {
+//% GPBType valueType = GPBGetFieldType(field);
+//% GPBType keyType = field.mapKeyType;
+//% uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+//% [_dictionary enumerateKeysAndObjectsUsingBlock:^(ENUM_TYPE##KHELPER(KEY_TYPE)##aKey,
+//% ENUM_TYPE##VHELPER(VALUE_TYPE)##aValue,
+//% BOOL *stop) {
+//% #pragma unused(stop)
+//% // Write the tag.
+//% [outputStream writeInt32NoTag:tag];
+//% // Write the size of the message.
+//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyType);
+//% msgSize += ComputeDict##VALUE_NAME##FieldSize(UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueType);
+//% [outputStream writeInt32NoTag:(int32_t)msgSize];
+//% // Write the fields.
+//% WriteDict##KEY_NAME##Field(outputStream, UNWRAP##KEY_NAME(aKey), kMapKeyFieldNumber, keyType);
+//% WriteDict##VALUE_NAME##Field(outputStream, UNWRAP##VALUE_NAME(aValue), kMapValueFieldNumber, valueType);
+//% }];
+//%}
+//%
+//%SERIAL_DATA_FOR_ENTRY_##VHELPER(KEY_NAME, VALUE_NAME)- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+//% [_dictionary setObject:WRAPPED##VHELPER(value->##GPBVALUE_##VHELPER(VALUE_NAME)##) forKey:WRAPPED##KHELPER(key->value##KEY_NAME)];
+//%}
+//%
+//%- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+//% [self enumerateKeysAnd##ACCESSOR_NAME##ValuesUsingBlock:^(KEY_TYPE KisP##key, VALUE_TYPE value, BOOL *stop) {
+//% #pragma unused(stop)
+//% block(TEXT_FORMAT_OBJ##KEY_NAME(key), TEXT_FORMAT_OBJ##VALUE_NAME(value));
+//% }];
+//%}
+//%PDDM-DEFINE DICTIONARY_MUTABLE_CORE(KEY_NAME, KEY_TYPE, KisP, VALUE_NAME, VALUE_TYPE, KHELPER, VHELPER, ACCESSOR_NAME)
+//%- (void)add##ACCESSOR_NAME##EntriesFromDictionary:(GPB##KEY_NAME##VALUE_NAME##Dictionary *)otherDictionary {
+//% if (otherDictionary) {
+//% [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+//% }
+//%}
+//%
+//%- (void)set##ACCESSOR_NAME##Value:(VALUE_TYPE)value forKey:(KEY_TYPE##KisP$S##KisP)key {
+//% [_dictionary setObject:WRAPPED##VHELPER(value) forKey:WRAPPED##KHELPER(key)];
+//%}
+//%
+//%- (void)removeValueForKey:(KEY_TYPE##KisP$S##KisP)aKey {
+//% [_dictionary removeObjectForKey:WRAPPED##KHELPER(aKey)];
+//%}
+//%
+//%- (void)removeAll {
+//% [_dictionary removeAllObjects];
+//%}
+
+//
+// Custom Generation for Bool keys
+//
+
+//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_POD_IMPL(VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, POD)
+//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_OBJECT_IMPL(VALUE_NAME, VALUE_TYPE)
+//%DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, OBJECT)
+
+//%PDDM-DEFINE DICTIONARY_BOOL_KEY_TO_VALUE_IMPL(VALUE_NAME, VALUE_TYPE, HELPER)
+//%#pragma mark - Bool -> VALUE_NAME
+//%
+//%@implementation GPBBool##VALUE_NAME##Dictionary {
+//% @package
+//% VALUE_TYPE _values[2];
+//%BOOL_DICT_HAS_STORAGE_##HELPER()}
+//%
+//%+ (instancetype)dictionary {
+//% return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValue:(VALUE_TYPE)value
+//% forKey:(BOOL)key {
+//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//% // on to get the type correct.
+//% return [[(GPBBool##VALUE_NAME##Dictionary*)[self alloc] initWithValues:&value
+//% VALUE_NAME$S forKeys:&key
+//% VALUE_NAME$S count:1] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithValues:(const VALUE_TYPE [])values
+//% forKeys:(const BOOL [])keys
+//% count:(NSUInteger)count {
+//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//% // on to get the type correct.
+//% return [[(GPBBool##VALUE_NAME##Dictionary*)[self alloc] initWithValues:values
+//% VALUE_NAME$S forKeys:keys
+//% VALUE_NAME$S count:count] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary {
+//% // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+//% // on to get the type correct.
+//% return [[(GPBBool##VALUE_NAME##Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+//%}
+//%
+//%+ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+//% return [[[self alloc] initWithCapacity:numItems] autorelease];
+//%}
+//%
+//%- (instancetype)init {
+//% return [self initWithValues:NULL forKeys:NULL count:0];
+//%}
+//%
+//%BOOL_DICT_INITS_##HELPER(VALUE_NAME, VALUE_TYPE)
+//%
+//%- (instancetype)initWithCapacity:(NSUInteger)numItems {
+//% #pragma unused(numItems)
+//% return [self initWithValues:NULL forKeys:NULL count:0];
+//%}
+//%
+//%BOOL_DICT_DEALLOC##HELPER()- (instancetype)copyWithZone:(NSZone *)zone {
+//% return [[GPBBool##VALUE_NAME##Dictionary allocWithZone:zone] initWithDictionary:self];
+//%}
+//%
+//%- (BOOL)isEqual:(GPBBool##VALUE_NAME##Dictionary *)other {
+//% if (self == other) {
+//% return YES;
+//% }
+//% if (![other isKindOfClass:[GPBBool##VALUE_NAME##Dictionary class]]) {
+//% return NO;
+//% }
+//% if ((BOOL_DICT_W_HAS##HELPER(0, ) != BOOL_DICT_W_HAS##HELPER(0, other->)) ||
+//% (BOOL_DICT_W_HAS##HELPER(1, ) != BOOL_DICT_W_HAS##HELPER(1, other->))) {
+//% return NO;
+//% }
+//% if ((BOOL_DICT_W_HAS##HELPER(0, ) && (NEQ_##HELPER(_values[0], other->_values[0]))) ||
+//% (BOOL_DICT_W_HAS##HELPER(1, ) && (NEQ_##HELPER(_values[1], other->_values[1])))) {
+//% return NO;
+//% }
+//% return YES;
+//%}
+//%
+//%- (NSUInteger)hash {
+//% return (BOOL_DICT_W_HAS##HELPER(0, ) ? 1 : 0) + (BOOL_DICT_W_HAS##HELPER(1, ) ? 1 : 0);
+//%}
+//%
+//%- (NSString *)description {
+//% NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+//% if (BOOL_DICT_W_HAS##HELPER(0, )) {
+//% [result appendFormat:@"NO: STR_FORMAT_##HELPER(VALUE_NAME)", _values[0]];
+//% }
+//% if (BOOL_DICT_W_HAS##HELPER(1, )) {
+//% [result appendFormat:@"YES: STR_FORMAT_##HELPER(VALUE_NAME)", _values[1]];
+//% }
+//% [result appendString:@" }"];
+//% return result;
+//%}
+//%
+//%- (NSUInteger)count {
+//% return (BOOL_DICT_W_HAS##HELPER(0, ) ? 1 : 0) + (BOOL_DICT_W_HAS##HELPER(1, ) ? 1 : 0);
+//%}
+//%
+//%BOOL_VALUE_FOR_KEY_##HELPER(VALUE_TYPE)
+//%
+//%BOOL_SET_GPBVALUE_FOR_KEY_##HELPER(VALUE_NAME, VALUE_TYPE, VisP)
+//%
+//%- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+//% if (BOOL_DICT_HAS##HELPER(0, )) {
+//% block(@"false", TEXT_FORMAT_OBJ##VALUE_NAME(_values[0]));
+//% }
+//% if (BOOL_DICT_W_HAS##HELPER(1, )) {
+//% block(@"true", TEXT_FORMAT_OBJ##VALUE_NAME(_values[1]));
+//% }
+//%}
+//%
+//%- (void)enumerateKeysAndValuesUsingBlock:
+//% (void (^)(BOOL key, VALUE_TYPE value, BOOL *stop))block {
+//% BOOL stop = NO;
+//% if (BOOL_DICT_HAS##HELPER(0, )) {
+//% block(NO, _values[0], &stop);
+//% }
+//% if (!stop && BOOL_DICT_W_HAS##HELPER(1, )) {
+//% block(YES, _values[1], &stop);
+//% }
+//%}
+//%
+//%BOOL_EXTRA_METHODS_##HELPER(Bool, VALUE_NAME)- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+//% GPBType valueType = GPBGetFieldType(field);
+//% NSUInteger count = 0;
+//% size_t result = 0;
+//% for (int i = 0; i < 2; ++i) {
+//% if (BOOL_DICT_HAS##HELPER(i, )) {
+//% ++count;
+//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueType);
+//% result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+//% }
+//% }
+//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+//% result += tagSize * count;
+//% return result;
+//%}
+//%
+//%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+//% asField:(GPBFieldDescriptor *)field {
+//% GPBType valueType = GPBGetFieldType(field);
+//% uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+//% for (int i = 0; i < 2; ++i) {
+//% if (BOOL_DICT_HAS##HELPER(i, )) {
+//% // Write the tag.
+//% [outputStream writeInt32NoTag:tag];
+//% // Write the size of the message.
+//% size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+//% msgSize += ComputeDict##VALUE_NAME##FieldSize(_values[i], kMapValueFieldNumber, valueType);
+//% [outputStream writeInt32NoTag:(int32_t)msgSize];
+//% // Write the fields.
+//% WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
+//% WriteDict##VALUE_NAME##Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+//% }
+//% }
+//%}
+//%
+//%BOOL_DICT_MUTATIONS_##HELPER(VALUE_NAME, VALUE_TYPE)
+//%
+//%@end
+//%
+
+
+//
+// Helpers for PODs
+//
+
+//%PDDM-DEFINE VALUE_FOR_KEY_POD(KEY_TYPE, VALUE_NAME, VALUE_TYPE, KHELPER)
+//%- (BOOL)valueForKey:(KEY_TYPE)key value:(VALUE_TYPE *)value {
+//% NSNumber *wrapped = [_dictionary objectForKey:WRAPPED##KHELPER(key)];
+//% if (wrapped && value) {
+//% *value = UNWRAP##VALUE_NAME(wrapped);
+//% }
+//% return (wrapped != NULL);
+//%}
+//%PDDM-DEFINE WRAPPEDPOD(VALUE)
+//%@(VALUE)
+//%PDDM-DEFINE UNWRAPUInt32(VALUE)
+//%[VALUE unsignedIntValue]
+//%PDDM-DEFINE UNWRAPInt32(VALUE)
+//%[VALUE intValue]
+//%PDDM-DEFINE UNWRAPUInt64(VALUE)
+//%[VALUE unsignedLongLongValue]
+//%PDDM-DEFINE UNWRAPInt64(VALUE)
+//%[VALUE longLongValue]
+//%PDDM-DEFINE UNWRAPBool(VALUE)
+//%[VALUE boolValue]
+//%PDDM-DEFINE UNWRAPFloat(VALUE)
+//%[VALUE floatValue]
+//%PDDM-DEFINE UNWRAPDouble(VALUE)
+//%[VALUE doubleValue]
+//%PDDM-DEFINE UNWRAPEnum(VALUE)
+//%[VALUE intValue]
+//%PDDM-DEFINE TEXT_FORMAT_OBJUInt32(VALUE)
+//%[NSString stringWithFormat:@"%u", VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJInt32(VALUE)
+//%[NSString stringWithFormat:@"%d", VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJUInt64(VALUE)
+//%[NSString stringWithFormat:@"%llu", VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJInt64(VALUE)
+//%[NSString stringWithFormat:@"%lld", VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJBool(VALUE)
+//%(VALUE ? @"true" : @"false")
+//%PDDM-DEFINE TEXT_FORMAT_OBJFloat(VALUE)
+//%[NSString stringWithFormat:@"%.*g", FLT_DIG, VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJDouble(VALUE)
+//%[NSString stringWithFormat:@"%.*lg", DBL_DIG, VALUE]
+//%PDDM-DEFINE TEXT_FORMAT_OBJEnum(VALUE)
+//%@(VALUE)
+//%PDDM-DEFINE ENUM_TYPEPOD(TYPE)
+//%NSNumber *
+//%PDDM-DEFINE NEQ_POD(VAL1, VAL2)
+//%VAL1 != VAL2
+//%PDDM-DEFINE EXTRA_METHODS_POD(KEY_NAME, VALUE_NAME)
+// Empty
+//%PDDM-DEFINE BOOL_EXTRA_METHODS_POD(KEY_NAME, VALUE_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD(KEY_NAME, VALUE_NAME)
+//%SERIAL_DATA_FOR_ENTRY_POD_##VALUE_NAME(KEY_NAME)
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_UInt32(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Int32(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_UInt64(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Int64(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Bool(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Float(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Double(KEY_NAME)
+// Empty
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_POD_Enum(KEY_NAME)
+//%- (NSData *)serializedDataForUnknownValue:(int32_t)value
+//% forKey:(GPBValue *)key
+//% keyType:(GPBType)keyType {
+//% size_t msgSize = ComputeDict##KEY_NAME##FieldSize(key->value##KEY_NAME, kMapKeyFieldNumber, keyType);
+//% msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+//% NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+//% GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+//% WriteDict##KEY_NAME##Field(outputStream, key->value##KEY_NAME, kMapKeyFieldNumber, keyType);
+//% WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+//% [outputStream release];
+//% return data;
+//%}
+//%
+//%PDDM-DEFINE GPBVALUE_POD(VALUE_NAME)
+//%value##VALUE_NAME
+
+//%PDDM-DEFINE BOOL_DICT_HAS_STORAGE_POD()
+//% BOOL _valueSet[2];
+//%
+//%PDDM-DEFINE BOOL_DICT_INITS_POD(VALUE_NAME, VALUE_TYPE)
+//%- (instancetype)initWithValues:(const VALUE_TYPE [])values
+//% forKeys:(const BOOL [])keys
+//% count:(NSUInteger)count {
+//% self = [super init];
+//% if (self) {
+//% for (NSUInteger i = 0; i < count; ++i) {
+//% int idx = keys[i] ? 1 : 0;
+//% _values[idx] = values[i];
+//% _valueSet[idx] = YES;
+//% }
+//% }
+//% return self;
+//%}
+//%
+//%- (instancetype)initWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary {
+//% self = [self initWithValues:NULL forKeys:NULL count:0];
+//% if (self) {
+//% if (dictionary) {
+//% for (int i = 0; i < 2; ++i) {
+//% if (dictionary->_valueSet[i]) {
+//% _values[i] = dictionary->_values[i];
+//% _valueSet[i] = YES;
+//% }
+//% }
+//% }
+//% }
+//% return self;
+//%}
+//%PDDM-DEFINE BOOL_DICT_DEALLOCPOD()
+// Empty
+//%PDDM-DEFINE BOOL_DICT_W_HASPOD(IDX, REF)
+//%BOOL_DICT_HASPOD(IDX, REF)
+//%PDDM-DEFINE BOOL_DICT_HASPOD(IDX, REF)
+//%REF##_valueSet[IDX]
+//%PDDM-DEFINE BOOL_VALUE_FOR_KEY_POD(VALUE_TYPE)
+//%- (BOOL)valueForKey:(BOOL)key value:(VALUE_TYPE *)value {
+//% int idx = (key ? 1 : 0);
+//% if (_valueSet[idx]) {
+//% if (value) {
+//% *value = _values[idx];
+//% }
+//% return YES;
+//% }
+//% return NO;
+//%}
+//%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_POD(VALUE_NAME, VALUE_TYPE, VisP)
+//%- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+//% int idx = (key->valueBool ? 1 : 0);
+//% _values[idx] = value->value##VALUE_NAME;
+//% _valueSet[idx] = YES;
+//%}
+//%PDDM-DEFINE BOOL_DICT_MUTATIONS_POD(VALUE_NAME, VALUE_TYPE)
+//%- (void)addEntriesFromDictionary:(GPBBool##VALUE_NAME##Dictionary *)otherDictionary {
+//% if (otherDictionary) {
+//% for (int i = 0; i < 2; ++i) {
+//% if (otherDictionary->_valueSet[i]) {
+//% _valueSet[i] = YES;
+//% _values[i] = otherDictionary->_values[i];
+//% }
+//% }
+//% }
+//%}
+//%
+//%- (void)setValue:(VALUE_TYPE)value forKey:(BOOL)key {
+//% int idx = (key ? 1 : 0);
+//% _values[idx] = value;
+//% _valueSet[idx] = YES;
+//%}
+//%
+//%- (void)removeValueForKey:(BOOL)aKey {
+//% _valueSet[aKey ? 1 : 0] = NO;
+//%}
+//%
+//%- (void)removeAll {
+//% _valueSet[0] = NO;
+//% _valueSet[1] = NO;
+//%}
+//%PDDM-DEFINE STR_FORMAT_POD(VALUE_NAME)
+//%STR_FORMAT_##VALUE_NAME()
+//%PDDM-DEFINE STR_FORMAT_UInt32()
+//%%u
+//%PDDM-DEFINE STR_FORMAT_Int32()
+//%%d
+//%PDDM-DEFINE STR_FORMAT_UInt64()
+//%%llu
+//%PDDM-DEFINE STR_FORMAT_Int64()
+//%%lld
+//%PDDM-DEFINE STR_FORMAT_Bool()
+//%%d
+//%PDDM-DEFINE STR_FORMAT_Float()
+//%%f
+//%PDDM-DEFINE STR_FORMAT_Double()
+//%%lf
+
+//
+// Helpers for Objects
+//
+
+//%PDDM-DEFINE VALUE_FOR_KEY_OBJECT(KEY_TYPE, VALUE_NAME, VALUE_TYPE, KHELPER)
+//%- (VALUE_TYPE)valueForKey:(KEY_TYPE)key {
+//% VALUE_TYPE result = [_dictionary objectForKey:WRAPPED##KHELPER(key)];
+//% return result;
+//%}
+//%PDDM-DEFINE WRAPPEDOBJECT(VALUE)
+//%VALUE
+//%PDDM-DEFINE UNWRAPString(VALUE)
+//%VALUE
+//%PDDM-DEFINE UNWRAPObject(VALUE)
+//%VALUE
+//%PDDM-DEFINE TEXT_FORMAT_OBJString(VALUE)
+//%VALUE
+//%PDDM-DEFINE TEXT_FORMAT_OBJObject(VALUE)
+//%VALUE
+//%PDDM-DEFINE ENUM_TYPEOBJECT(TYPE)
+//%ENUM_TYPEOBJECT_##TYPE()
+//%PDDM-DEFINE ENUM_TYPEOBJECT_NSString()
+//%NSString *
+//%PDDM-DEFINE ENUM_TYPEOBJECT_id()
+//%id ##
+//%PDDM-DEFINE NEQ_OBJECT(VAL1, VAL2)
+//%![VAL1 isEqual:VAL2]
+//%PDDM-DEFINE EXTRA_METHODS_OBJECT(KEY_NAME, VALUE_NAME)
+//%- (BOOL)isInitialized {
+//% for (GPBMessage *msg in [_dictionary objectEnumerator]) {
+//% if (!msg.initialized) {
+//% return NO;
+//% }
+//% }
+//% return YES;
+//%}
+//%
+//%- (instancetype)deepCopyWithZone:(NSZone *)zone {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *newDict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//% [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
+//% GPBMessage *msg,
+//% BOOL *stop) {
+//% #pragma unused(stop)
+//% GPBMessage *copiedMsg = [msg copyWithZone:zone];
+//% [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+//% [copiedMsg release];
+//% }];
+//% return newDict;
+//%}
+//%
+//%
+//%PDDM-DEFINE BOOL_EXTRA_METHODS_OBJECT(KEY_NAME, VALUE_NAME)
+//%- (BOOL)isInitialized {
+//% if (_values[0] && ![_values[0] isInitialized]) {
+//% return NO;
+//% }
+//% if (_values[1] && ![_values[1] isInitialized]) {
+//% return NO;
+//% }
+//% return YES;
+//%}
+//%
+//%- (instancetype)deepCopyWithZone:(NSZone *)zone {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *newDict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//% for (int i = 0; i < 2; ++i) {
+//% if (_values[i] != nil) {
+//% newDict->_values[i] = [_values[i] copyWithZone:zone];
+//% }
+//% }
+//% return newDict;
+//%}
+//%
+//%
+//%PDDM-DEFINE SERIAL_DATA_FOR_ENTRY_OBJECT(KEY_NAME, VALUE_NAME)
+// Empty
+//%PDDM-DEFINE GPBVALUE_OBJECT(VALUE_NAME)
+//%valueString
+
+
+//%PDDM-DEFINE BOOL_DICT_HAS_STORAGE_OBJECT()
+// Empty
+//%PDDM-DEFINE BOOL_DICT_INITS_OBJECT(VALUE_NAME, VALUE_TYPE)
+//%- (instancetype)initWithValues:(const VALUE_TYPE [])values
+//% forKeys:(const BOOL [])keys
+//% count:(NSUInteger)count {
+//% self = [super init];
+//% if (self) {
+//% for (NSUInteger i = 0; i < count; ++i) {
+//% int idx = keys[i] ? 1 : 0;
+//% [_values[idx] release];
+//% _values[idx] = (VALUE_TYPE)[values[i] retain];
+//% }
+//% }
+//% return self;
+//%}
+//%
+//%- (instancetype)initWithDictionary:(GPBBool##VALUE_NAME##Dictionary *)dictionary {
+//% self = [self initWithValues:NULL forKeys:NULL count:0];
+//% if (self) {
+//% if (dictionary) {
+//% _values[0] = [dictionary->_values[0] retain];
+//% _values[1] = [dictionary->_values[1] retain];
+//% }
+//% }
+//% return self;
+//%}
+//%PDDM-DEFINE BOOL_DICT_DEALLOCOBJECT()
+//%- (void)dealloc {
+//% [_values[0] release];
+//% [_values[1] release];
+//% [super dealloc];
+//%}
+//%
+//%
+//%PDDM-DEFINE BOOL_DICT_W_HASOBJECT(IDX, REF)
+//%(BOOL_DICT_HASOBJECT(IDX, REF))
+//%PDDM-DEFINE BOOL_DICT_HASOBJECT(IDX, REF)
+//%REF##_values[IDX] != nil
+//%PDDM-DEFINE BOOL_VALUE_FOR_KEY_OBJECT(VALUE_TYPE)
+//%- (VALUE_TYPE)valueForKey:(BOOL)key {
+//% return _values[key ? 1 : 0];
+//%}
+//%PDDM-DEFINE BOOL_SET_GPBVALUE_FOR_KEY_OBJECT(VALUE_NAME, VALUE_TYPE, VisP)
+//%- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+//% int idx = (key->valueBool ? 1 : 0);
+//% [_values[idx] release];
+//% _values[idx] = [value->valueString retain];
+//%}
+
+//%PDDM-DEFINE BOOL_DICT_MUTATIONS_OBJECT(VALUE_NAME, VALUE_TYPE)
+//%- (void)addEntriesFromDictionary:(GPBBool##VALUE_NAME##Dictionary *)otherDictionary {
+//% if (otherDictionary) {
+//% for (int i = 0; i < 2; ++i) {
+//% if (otherDictionary->_values[i] != nil) {
+//% [_values[i] release];
+//% _values[i] = [otherDictionary->_values[i] retain];
+//% }
+//% }
+//% }
+//%}
+//%
+//%- (void)setValue:(VALUE_TYPE)value forKey:(BOOL)key {
+//% int idx = (key ? 1 : 0);
+//% [_values[idx] release];
+//% _values[idx] = [value retain];
+//%}
+//%
+//%- (void)removeValueForKey:(BOOL)aKey {
+//% int idx = (aKey ? 1 : 0);
+//% [_values[idx] release];
+//% _values[idx] = nil;
+//%}
+//%
+//%- (void)removeAll {
+//% for (int i = 0; i < 2; ++i) {
+//% [_values[i] release];
+//% _values[i] = nil;
+//% }
+//%}
+//%PDDM-DEFINE STR_FORMAT_OBJECT(VALUE_NAME)
+//%%@
+
+
+//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt32, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt32 -> UInt32
+
+@implementation GPBUInt32UInt32Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(uint32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32UInt32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32UInt32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32UInt32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt32UInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32UInt32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt32UInt32Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, uint32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedIntValue], [aValue unsignedIntValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, uint32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%u", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(uint32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped unsignedIntValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32UInt32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(uint32_t)value forKey:(uint32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Int32
+
+@implementation GPBUInt32Int32Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(uint32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32Int32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32Int32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32Int32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32Int32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt32Int32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32Int32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt32Int32Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, int32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedIntValue], [aValue intValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%d", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(int32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped intValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32Int32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(int32_t)value forKey:(uint32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> UInt64
+
+@implementation GPBUInt32UInt64Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(uint32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32UInt64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32UInt64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32UInt64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt32UInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32UInt64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt32UInt64Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, uint64_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedIntValue], [aValue unsignedLongLongValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, uint64_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%llu", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(uint64_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped unsignedLongLongValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32UInt64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(uint64_t)value forKey:(uint32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Int64
+
+@implementation GPBUInt32Int64Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(uint32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32Int64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32Int64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32Int64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32Int64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt32Int64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32Int64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt32Int64Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, int64_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedIntValue], [aValue longLongValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, int64_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%lld", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(int64_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped longLongValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32Int64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(int64_t)value forKey:(uint32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Bool
+
+@implementation GPBUInt32BoolDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(uint32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32BoolDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32BoolDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32BoolDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32BoolDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt32BoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32BoolDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt32BoolDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, BOOL value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedIntValue], [aValue boolValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, BOOL value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%u", key], (value ? @"true" : @"false"));
+ }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(BOOL *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped boolValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32BoolDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(BOOL)value forKey:(uint32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Float
+
+@implementation GPBUInt32FloatDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(uint32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32FloatDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32FloatDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32FloatDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32FloatDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt32FloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32FloatDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt32FloatDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, float value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedIntValue], [aValue floatValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, float value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(float *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped floatValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32FloatDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(float)value forKey:(uint32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Double
+
+@implementation GPBUInt32DoubleDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(uint32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32DoubleDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32DoubleDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32DoubleDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32DoubleDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt32DoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32DoubleDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt32DoubleDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, double value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedIntValue], [aValue doubleValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, double value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(double *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped doubleValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32DoubleDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(double)value forKey:(uint32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt32 -> Enum
+
+@implementation GPBUInt32EnumDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+ GPBEnumValidationFunc _validationFunc;
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValidationFunction:NULL
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [[[self alloc] initWithValidationFunction:func
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(uint32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:&rawValue
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:rawValues
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32EnumDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+ if (count && rawValues && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32EnumDictionary *)dictionary {
+ self = [self initWithValidationFunction:dictionary.validationFunc
+ rawValues:NULL
+ forKeys:NULL
+ count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt32EnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32EnumDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt32EnumDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(uint32_t key, int32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedIntValue], [aValue intValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType {
+ size_t msgSize = ComputeDictUInt32FieldSize(key->valueUInt32, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+ NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+ GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+ WriteDictUInt32Field(outputStream, key->valueUInt32, kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+ [outputStream release];
+ return data;
+}
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndRawValuesUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%u", key], @(value));
+ }];
+}
+
+- (BOOL)valueForKey:(uint32_t)key value:(int32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ int32_t result = [wrapped intValue];
+ if (!_validationFunc(result)) {
+ result = kGPBUnrecognizedEnumeratorValue;
+ }
+ *value = result;
+ }
+ return (wrapped != NULL);
+}
+
+- (BOOL)valueForKey:(uint32_t)key rawValue:(int32_t *)rawValue {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && rawValue) {
+ *rawValue = [wrapped intValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, int32_t value, BOOL *stop))block {
+ GPBEnumValidationFunc func = _validationFunc;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ int32_t unwrapped = [aValue intValue];
+ if (!func(unwrapped)) {
+ unwrapped = kGPBUnrecognizedEnumeratorValue;
+ }
+ block([aKey unsignedIntValue], unwrapped, stop);
+ }];
+}
+
+- (void)addRawEntriesFromDictionary:(GPBUInt32EnumDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setRawValue:(int32_t)value forKey:(uint32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+- (void)setValue:(int32_t)value forKey:(uint32_t)key {
+ if (!_validationFunc(value)) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"GPBUInt32EnumDictionary: Attempt to set an unknown enum value (%d)",
+ value];
+ }
+
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+@end
+
+#pragma mark - UInt32 -> Object
+
+@implementation GPBUInt32ObjectDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(id)value
+ forKey:(uint32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32ObjectDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const id [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32ObjectDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt32ObjectDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt32ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const id [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:values[i] forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt32ObjectDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt32ObjectDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt32ObjectDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt32ObjectDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint32_t key, id value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ block([aKey unsignedIntValue], aValue, stop);
+ }];
+}
+
+- (BOOL)isInitialized {
+ for (GPBMessage *msg in [_dictionary objectEnumerator]) {
+ if (!msg.initialized) {
+ return NO;
+ }
+ }
+ return YES;
+}
+
+- (instancetype)deepCopyWithZone:(NSZone *)zone {
+ GPBUInt32ObjectDictionary *newDict =
+ [[GPBUInt32ObjectDictionary alloc] init];
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
+ GPBMessage *msg,
+ BOOL *stop) {
+ #pragma unused(stop)
+ GPBMessage *copiedMsg = [msg copyWithZone:zone];
+ [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+ [copiedMsg release];
+ }];
+ return newDict;
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt32FieldSize([aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt32Field(outputStream, [aKey unsignedIntValue], kMapKeyFieldNumber, keyType);
+ WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:value->valueString forKey:@(key->valueUInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint32_t key, id value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%u", key], value);
+ }];
+}
+
+- (id)valueForKey:(uint32_t)key {
+ id result = [_dictionary objectForKey:@(key)];
+ return result;
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt32ObjectDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(id)value forKey:(uint32_t)key {
+ [_dictionary setObject:value forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int32, int32_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32 -> UInt32
+
+@implementation GPBInt32UInt32Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(int32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32UInt32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32UInt32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32UInt32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32UInt32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt32UInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32UInt32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt32UInt32Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, uint32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey intValue], [aValue unsignedIntValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
+ WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int32_t key, uint32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%u", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(uint32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped unsignedIntValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32UInt32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(uint32_t)value forKey:(int32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Int32
+
+@implementation GPBInt32Int32Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(int32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32Int32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32Int32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32Int32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32Int32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt32Int32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32Int32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt32Int32Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, int32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey intValue], [aValue intValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
+ WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int32_t key, int32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%d", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(int32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped intValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32Int32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(int32_t)value forKey:(int32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> UInt64
+
+@implementation GPBInt32UInt64Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(int32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32UInt64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32UInt64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32UInt64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32UInt64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt32UInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32UInt64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt32UInt64Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, uint64_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey intValue], [aValue unsignedLongLongValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
+ WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int32_t key, uint64_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%llu", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(uint64_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped unsignedLongLongValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32UInt64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(uint64_t)value forKey:(int32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Int64
+
+@implementation GPBInt32Int64Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(int32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32Int64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32Int64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32Int64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32Int64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt32Int64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32Int64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt32Int64Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, int64_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey intValue], [aValue longLongValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
+ WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int32_t key, int64_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%lld", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(int64_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped longLongValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32Int64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(int64_t)value forKey:(int32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Bool
+
+@implementation GPBInt32BoolDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(int32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32BoolDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32BoolDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32BoolDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32BoolDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt32BoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32BoolDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt32BoolDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, BOOL value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey intValue], [aValue boolValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
+ WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int32_t key, BOOL value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%d", key], (value ? @"true" : @"false"));
+ }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(BOOL *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped boolValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32BoolDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(BOOL)value forKey:(int32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Float
+
+@implementation GPBInt32FloatDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(int32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32FloatDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32FloatDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32FloatDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32FloatDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt32FloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32FloatDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt32FloatDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, float value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey intValue], [aValue floatValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
+ WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int32_t key, float value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(float *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped floatValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32FloatDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(float)value forKey:(int32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Double
+
+@implementation GPBInt32DoubleDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(int32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32DoubleDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32DoubleDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32DoubleDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32DoubleDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt32DoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32DoubleDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt32DoubleDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, double value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey intValue], [aValue doubleValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
+ WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int32_t key, double value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(double *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped doubleValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32DoubleDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(double)value forKey:(int32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int32 -> Enum
+
+@implementation GPBInt32EnumDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+ GPBEnumValidationFunc _validationFunc;
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValidationFunction:NULL
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [[[self alloc] initWithValidationFunction:func
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(int32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32EnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:&rawValue
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32EnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:rawValues
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32EnumDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+ if (count && rawValues && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32EnumDictionary *)dictionary {
+ self = [self initWithValidationFunction:dictionary.validationFunc
+ rawValues:NULL
+ forKeys:NULL
+ count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt32EnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32EnumDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt32EnumDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(int32_t key, int32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey intValue], [aValue intValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType {
+ size_t msgSize = ComputeDictInt32FieldSize(key->valueInt32, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+ NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+ GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+ WriteDictInt32Field(outputStream, key->valueInt32, kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+ [outputStream release];
+ return data;
+}
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndRawValuesUsingBlock:^(int32_t key, int32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%d", key], @(value));
+ }];
+}
+
+- (BOOL)valueForKey:(int32_t)key value:(int32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ int32_t result = [wrapped intValue];
+ if (!_validationFunc(result)) {
+ result = kGPBUnrecognizedEnumeratorValue;
+ }
+ *value = result;
+ }
+ return (wrapped != NULL);
+}
+
+- (BOOL)valueForKey:(int32_t)key rawValue:(int32_t *)rawValue {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && rawValue) {
+ *rawValue = [wrapped intValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, int32_t value, BOOL *stop))block {
+ GPBEnumValidationFunc func = _validationFunc;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ int32_t unwrapped = [aValue intValue];
+ if (!func(unwrapped)) {
+ unwrapped = kGPBUnrecognizedEnumeratorValue;
+ }
+ block([aKey intValue], unwrapped, stop);
+ }];
+}
+
+- (void)addRawEntriesFromDictionary:(GPBInt32EnumDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setRawValue:(int32_t)value forKey:(int32_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+- (void)setValue:(int32_t)value forKey:(int32_t)key {
+ if (!_validationFunc(value)) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"GPBInt32EnumDictionary: Attempt to set an unknown enum value (%d)",
+ value];
+ }
+
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+@end
+
+#pragma mark - Int32 -> Object
+
+@implementation GPBInt32ObjectDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(id)value
+ forKey:(int32_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32ObjectDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const id [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32ObjectDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt32ObjectDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt32ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const id [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:values[i] forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt32ObjectDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt32ObjectDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt32ObjectDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt32ObjectDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int32_t key, id value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ block([aKey intValue], aValue, stop);
+ }];
+}
+
+- (BOOL)isInitialized {
+ for (GPBMessage *msg in [_dictionary objectEnumerator]) {
+ if (!msg.initialized) {
+ return NO;
+ }
+ }
+ return YES;
+}
+
+- (instancetype)deepCopyWithZone:(NSZone *)zone {
+ GPBInt32ObjectDictionary *newDict =
+ [[GPBInt32ObjectDictionary alloc] init];
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
+ GPBMessage *msg,
+ BOOL *stop) {
+ #pragma unused(stop)
+ GPBMessage *copiedMsg = [msg copyWithZone:zone];
+ [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+ [copiedMsg release];
+ }];
+ return newDict;
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt32FieldSize([aKey intValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt32Field(outputStream, [aKey intValue], kMapKeyFieldNumber, keyType);
+ WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:value->valueString forKey:@(key->valueInt32)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int32_t key, id value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%d", key], value);
+ }];
+}
+
+- (id)valueForKey:(int32_t)key {
+ id result = [_dictionary objectForKey:@(key)];
+ return result;
+}
+
+- (void)addEntriesFromDictionary:(GPBInt32ObjectDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(id)value forKey:(int32_t)key {
+ [_dictionary setObject:value forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int32_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt64, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt64 -> UInt32
+
+@implementation GPBUInt64UInt32Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(uint64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64UInt32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64UInt32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64UInt32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt64UInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64UInt32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt64UInt32Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, uint32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedLongLongValue], [aValue unsignedIntValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, uint32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%u", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(uint32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped unsignedIntValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64UInt32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(uint32_t)value forKey:(uint64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Int32
+
+@implementation GPBUInt64Int32Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(uint64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64Int32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64Int32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64Int32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64Int32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt64Int32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64Int32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt64Int32Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, int32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedLongLongValue], [aValue intValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%d", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(int32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped intValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64Int32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(int32_t)value forKey:(uint64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> UInt64
+
+@implementation GPBUInt64UInt64Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(uint64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64UInt64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64UInt64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64UInt64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt64UInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64UInt64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt64UInt64Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, uint64_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedLongLongValue], [aValue unsignedLongLongValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, uint64_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%llu", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(uint64_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped unsignedLongLongValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64UInt64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(uint64_t)value forKey:(uint64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Int64
+
+@implementation GPBUInt64Int64Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(uint64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64Int64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64Int64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64Int64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64Int64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt64Int64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64Int64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt64Int64Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, int64_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedLongLongValue], [aValue longLongValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, int64_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%lld", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(int64_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped longLongValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64Int64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(int64_t)value forKey:(uint64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Bool
+
+@implementation GPBUInt64BoolDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(uint64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64BoolDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64BoolDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64BoolDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64BoolDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt64BoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64BoolDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt64BoolDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, BOOL value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedLongLongValue], [aValue boolValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueBool) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, BOOL value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%llu", key], (value ? @"true" : @"false"));
+ }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(BOOL *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped boolValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64BoolDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(BOOL)value forKey:(uint64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Float
+
+@implementation GPBUInt64FloatDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(uint64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64FloatDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64FloatDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64FloatDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64FloatDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt64FloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64FloatDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt64FloatDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, float value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedLongLongValue], [aValue floatValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, float value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(float *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped floatValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64FloatDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(float)value forKey:(uint64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Double
+
+@implementation GPBUInt64DoubleDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(uint64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64DoubleDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64DoubleDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64DoubleDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64DoubleDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt64DoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64DoubleDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt64DoubleDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, double value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedLongLongValue], [aValue doubleValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, double value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
+ }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(double *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped doubleValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64DoubleDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(double)value forKey:(uint64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - UInt64 -> Enum
+
+@implementation GPBUInt64EnumDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+ GPBEnumValidationFunc _validationFunc;
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValidationFunction:NULL
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [[[self alloc] initWithValidationFunction:func
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(uint64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64EnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:&rawValue
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64EnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:rawValues
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64EnumDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+ if (count && rawValues && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64EnumDictionary *)dictionary {
+ self = [self initWithValidationFunction:dictionary.validationFunc
+ rawValues:NULL
+ forKeys:NULL
+ count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt64EnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64EnumDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt64EnumDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(uint64_t key, int32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey unsignedLongLongValue], [aValue intValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType {
+ size_t msgSize = ComputeDictUInt64FieldSize(key->valueUInt64, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+ NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+ GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+ WriteDictUInt64Field(outputStream, key->valueUInt64, kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+ [outputStream release];
+ return data;
+}
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndRawValuesUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%llu", key], @(value));
+ }];
+}
+
+- (BOOL)valueForKey:(uint64_t)key value:(int32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ int32_t result = [wrapped intValue];
+ if (!_validationFunc(result)) {
+ result = kGPBUnrecognizedEnumeratorValue;
+ }
+ *value = result;
+ }
+ return (wrapped != NULL);
+}
+
+- (BOOL)valueForKey:(uint64_t)key rawValue:(int32_t *)rawValue {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && rawValue) {
+ *rawValue = [wrapped intValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, int32_t value, BOOL *stop))block {
+ GPBEnumValidationFunc func = _validationFunc;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ int32_t unwrapped = [aValue intValue];
+ if (!func(unwrapped)) {
+ unwrapped = kGPBUnrecognizedEnumeratorValue;
+ }
+ block([aKey unsignedLongLongValue], unwrapped, stop);
+ }];
+}
+
+- (void)addRawEntriesFromDictionary:(GPBUInt64EnumDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setRawValue:(int32_t)value forKey:(uint64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+- (void)setValue:(int32_t)value forKey:(uint64_t)key {
+ if (!_validationFunc(value)) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"GPBUInt64EnumDictionary: Attempt to set an unknown enum value (%d)",
+ value];
+ }
+
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+@end
+
+#pragma mark - UInt64 -> Object
+
+@implementation GPBUInt64ObjectDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(id)value
+ forKey:(uint64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64ObjectDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const id [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64ObjectDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBUInt64ObjectDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBUInt64ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const id [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:values[i] forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBUInt64ObjectDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBUInt64ObjectDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBUInt64ObjectDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBUInt64ObjectDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(uint64_t key, id value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ block([aKey unsignedLongLongValue], aValue, stop);
+ }];
+}
+
+- (BOOL)isInitialized {
+ for (GPBMessage *msg in [_dictionary objectEnumerator]) {
+ if (!msg.initialized) {
+ return NO;
+ }
+ }
+ return YES;
+}
+
+- (instancetype)deepCopyWithZone:(NSZone *)zone {
+ GPBUInt64ObjectDictionary *newDict =
+ [[GPBUInt64ObjectDictionary alloc] init];
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
+ GPBMessage *msg,
+ BOOL *stop) {
+ #pragma unused(stop)
+ GPBMessage *copiedMsg = [msg copyWithZone:zone];
+ [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+ [copiedMsg release];
+ }];
+ return newDict;
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictUInt64FieldSize([aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictUInt64Field(outputStream, [aKey unsignedLongLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:value->valueString forKey:@(key->valueUInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(uint64_t key, id value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%llu", key], value);
+ }];
+}
+
+- (id)valueForKey:(uint64_t)key {
+ id result = [_dictionary objectForKey:@(key)];
+ return result;
+}
+
+- (void)addEntriesFromDictionary:(GPBUInt64ObjectDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(id)value forKey:(uint64_t)key {
+ [_dictionary setObject:value forKey:@(key)];
+}
+
+- (void)removeValueForKey:(uint64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int64, int64_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int64 -> UInt32
+
+@implementation GPBInt64UInt32Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(int64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64UInt32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64UInt32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64UInt32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64UInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64UInt32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt64UInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64UInt32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt64UInt32Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, uint32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey longLongValue], [aValue unsignedIntValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueUInt32) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int64_t key, uint32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%u", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(uint32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped unsignedIntValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64UInt32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(uint32_t)value forKey:(int64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Int32
+
+@implementation GPBInt64Int32Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(int64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64Int32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64Int32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64Int32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64Int32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64Int32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt64Int32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64Int32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt64Int32Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, int32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey longLongValue], [aValue intValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueInt32) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int64_t key, int32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%d", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(int32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped intValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64Int32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(int32_t)value forKey:(int64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> UInt64
+
+@implementation GPBInt64UInt64Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(int64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64UInt64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64UInt64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64UInt64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64UInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64UInt64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt64UInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64UInt64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt64UInt64Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, uint64_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey longLongValue], [aValue unsignedLongLongValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueUInt64) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int64_t key, uint64_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%llu", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(uint64_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped unsignedLongLongValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64UInt64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(uint64_t)value forKey:(int64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Int64
+
+@implementation GPBInt64Int64Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(int64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64Int64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64Int64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64Int64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64Int64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64Int64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt64Int64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64Int64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt64Int64Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, int64_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey longLongValue], [aValue longLongValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueInt64) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int64_t key, int64_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%lld", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(int64_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped longLongValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64Int64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(int64_t)value forKey:(int64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Bool
+
+@implementation GPBInt64BoolDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(int64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64BoolDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64BoolDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64BoolDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64BoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64BoolDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt64BoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64BoolDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt64BoolDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, BOOL value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey longLongValue], [aValue boolValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueBool) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int64_t key, BOOL value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%lld", key], (value ? @"true" : @"false"));
+ }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(BOOL *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped boolValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64BoolDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(BOOL)value forKey:(int64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Float
+
+@implementation GPBInt64FloatDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(int64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64FloatDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64FloatDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64FloatDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64FloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64FloatDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt64FloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64FloatDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt64FloatDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, float value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey longLongValue], [aValue floatValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueFloat) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int64_t key, float value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(float *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped floatValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64FloatDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(float)value forKey:(int64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Double
+
+@implementation GPBInt64DoubleDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(int64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64DoubleDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64DoubleDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64DoubleDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64DoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64DoubleDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt64DoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64DoubleDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt64DoubleDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, double value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey longLongValue], [aValue doubleValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueDouble) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int64_t key, double value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
+ }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(double *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ *value = [wrapped doubleValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64DoubleDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(double)value forKey:(int64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - Int64 -> Enum
+
+@implementation GPBInt64EnumDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+ GPBEnumValidationFunc _validationFunc;
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValidationFunction:NULL
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [[[self alloc] initWithValidationFunction:func
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(int64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64EnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:&rawValue
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64EnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:rawValues
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64EnumDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64EnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+ if (count && rawValues && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(rawValues[i]) forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64EnumDictionary *)dictionary {
+ self = [self initWithValidationFunction:dictionary.validationFunc
+ rawValues:NULL
+ forKeys:NULL
+ count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt64EnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64EnumDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt64EnumDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(int64_t key, int32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block([aKey longLongValue], [aValue intValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType {
+ size_t msgSize = ComputeDictInt64FieldSize(key->valueInt64, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+ NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+ GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+ WriteDictInt64Field(outputStream, key->valueInt64, kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+ [outputStream release];
+ return data;
+}
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueEnum) forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndRawValuesUsingBlock:^(int64_t key, int32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%lld", key], @(value));
+ }];
+}
+
+- (BOOL)valueForKey:(int64_t)key value:(int32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && value) {
+ int32_t result = [wrapped intValue];
+ if (!_validationFunc(result)) {
+ result = kGPBUnrecognizedEnumeratorValue;
+ }
+ *value = result;
+ }
+ return (wrapped != NULL);
+}
+
+- (BOOL)valueForKey:(int64_t)key rawValue:(int32_t *)rawValue {
+ NSNumber *wrapped = [_dictionary objectForKey:@(key)];
+ if (wrapped && rawValue) {
+ *rawValue = [wrapped intValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, int32_t value, BOOL *stop))block {
+ GPBEnumValidationFunc func = _validationFunc;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ int32_t unwrapped = [aValue intValue];
+ if (!func(unwrapped)) {
+ unwrapped = kGPBUnrecognizedEnumeratorValue;
+ }
+ block([aKey longLongValue], unwrapped, stop);
+ }];
+}
+
+- (void)addRawEntriesFromDictionary:(GPBInt64EnumDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setRawValue:(int32_t)value forKey:(int64_t)key {
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+- (void)setValue:(int32_t)value forKey:(int64_t)key {
+ if (!_validationFunc(value)) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"GPBInt64EnumDictionary: Attempt to set an unknown enum value (%d)",
+ value];
+ }
+
+ [_dictionary setObject:@(value) forKey:@(key)];
+}
+
+@end
+
+#pragma mark - Int64 -> Object
+
+@implementation GPBInt64ObjectDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(id)value
+ forKey:(int64_t)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64ObjectDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const id [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64ObjectDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBInt64ObjectDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBInt64ObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const id [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:values[i] forKey:@(keys[i])];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBInt64ObjectDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBInt64ObjectDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBInt64ObjectDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBInt64ObjectDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(int64_t key, id value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ block([aKey longLongValue], aValue, stop);
+ }];
+}
+
+- (BOOL)isInitialized {
+ for (GPBMessage *msg in [_dictionary objectEnumerator]) {
+ if (!msg.initialized) {
+ return NO;
+ }
+ }
+ return YES;
+}
+
+- (instancetype)deepCopyWithZone:(NSZone *)zone {
+ GPBInt64ObjectDictionary *newDict =
+ [[GPBInt64ObjectDictionary alloc] init];
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(id aKey,
+ GPBMessage *msg,
+ BOOL *stop) {
+ #pragma unused(stop)
+ GPBMessage *copiedMsg = [msg copyWithZone:zone];
+ [newDict->_dictionary setObject:copiedMsg forKey:aKey];
+ [copiedMsg release];
+ }];
+ return newDict;
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSNumber *aKey,
+ id aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictInt64FieldSize([aKey longLongValue], kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictObjectFieldSize(aValue, kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictInt64Field(outputStream, [aKey longLongValue], kMapKeyFieldNumber, keyType);
+ WriteDictObjectField(outputStream, aValue, kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:value->valueString forKey:@(key->valueInt64)];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(int64_t key, id value, BOOL *stop) {
+ #pragma unused(stop)
+ block([NSString stringWithFormat:@"%lld", key], value);
+ }];
+}
+
+- (id)valueForKey:(int64_t)key {
+ id result = [_dictionary objectForKey:@(key)];
+ return result;
+}
+
+- (void)addEntriesFromDictionary:(GPBInt64ObjectDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(id)value forKey:(int64_t)key {
+ [_dictionary setObject:value forKey:@(key)];
+}
+
+- (void)removeValueForKey:(int64_t)aKey {
+ [_dictionary removeObjectForKey:@(aKey)];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_POD_IMPL_FOR_KEY(String, NSString, *, OBJECT)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - String -> UInt32
+
+@implementation GPBStringUInt32Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(NSString *)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringUInt32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringUInt32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringUInt32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringUInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:keys[i]];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringUInt32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBStringUInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringUInt32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBStringUInt32Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, uint32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block(aKey, [aValue unsignedIntValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt32FieldSize([aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
+ WriteDictUInt32Field(outputStream, [aValue unsignedIntValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueUInt32) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(NSString *key, uint32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block(key, [NSString stringWithFormat:@"%u", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(uint32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:key];
+ if (wrapped && value) {
+ *value = [wrapped unsignedIntValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringUInt32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(uint32_t)value forKey:(NSString *)key {
+ [_dictionary setObject:@(value) forKey:key];
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+ [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Int32
+
+@implementation GPBStringInt32Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(NSString *)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringInt32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringInt32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringInt32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:keys[i]];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringInt32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBStringInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringInt32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBStringInt32Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, int32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block(aKey, [aValue intValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt32FieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
+ WriteDictInt32Field(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueInt32) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(NSString *key, int32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block(key, [NSString stringWithFormat:@"%d", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(int32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:key];
+ if (wrapped && value) {
+ *value = [wrapped intValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringInt32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(int32_t)value forKey:(NSString *)key {
+ [_dictionary setObject:@(value) forKey:key];
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+ [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> UInt64
+
+@implementation GPBStringUInt64Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(NSString *)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringUInt64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringUInt64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringUInt64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringUInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:keys[i]];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringUInt64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBStringUInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringUInt64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBStringUInt64Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, uint64_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block(aKey, [aValue unsignedLongLongValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictUInt64FieldSize([aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
+ WriteDictUInt64Field(outputStream, [aValue unsignedLongLongValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueUInt64) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(NSString *key, uint64_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block(key, [NSString stringWithFormat:@"%llu", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(uint64_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:key];
+ if (wrapped && value) {
+ *value = [wrapped unsignedLongLongValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringUInt64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(uint64_t)value forKey:(NSString *)key {
+ [_dictionary setObject:@(value) forKey:key];
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+ [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Int64
+
+@implementation GPBStringInt64Dictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(NSString *)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringInt64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringInt64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringInt64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:keys[i]];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringInt64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBStringInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringInt64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBStringInt64Dictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, int64_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block(aKey, [aValue longLongValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictInt64FieldSize([aValue longLongValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
+ WriteDictInt64Field(outputStream, [aValue longLongValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueInt64) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(NSString *key, int64_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block(key, [NSString stringWithFormat:@"%lld", value]);
+ }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(int64_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:key];
+ if (wrapped && value) {
+ *value = [wrapped longLongValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringInt64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(int64_t)value forKey:(NSString *)key {
+ [_dictionary setObject:@(value) forKey:key];
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+ [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Bool
+
+@implementation GPBStringBoolDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(NSString *)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringBoolDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringBoolDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringBoolDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringBoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:keys[i]];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringBoolDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBStringBoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringBoolDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBStringBoolDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, BOOL value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block(aKey, [aValue boolValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictBoolFieldSize([aValue boolValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
+ WriteDictBoolField(outputStream, [aValue boolValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueBool) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(NSString *key, BOOL value, BOOL *stop) {
+ #pragma unused(stop)
+ block(key, (value ? @"true" : @"false"));
+ }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(BOOL *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:key];
+ if (wrapped && value) {
+ *value = [wrapped boolValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringBoolDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(BOOL)value forKey:(NSString *)key {
+ [_dictionary setObject:@(value) forKey:key];
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+ [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Float
+
+@implementation GPBStringFloatDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(NSString *)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringFloatDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringFloatDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringFloatDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringFloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:keys[i]];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringFloatDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBStringFloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringFloatDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBStringFloatDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, float value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block(aKey, [aValue floatValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictFloatFieldSize([aValue floatValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
+ WriteDictFloatField(outputStream, [aValue floatValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueFloat) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(NSString *key, float value, BOOL *stop) {
+ #pragma unused(stop)
+ block(key, [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
+ }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(float *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:key];
+ if (wrapped && value) {
+ *value = [wrapped floatValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringFloatDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(float)value forKey:(NSString *)key {
+ [_dictionary setObject:@(value) forKey:key];
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+ [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Double
+
+@implementation GPBStringDoubleDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(NSString *)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringDoubleDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringDoubleDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringDoubleDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringDoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ if (count && values && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(values[i]) forKey:keys[i]];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringDoubleDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBStringDoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringDoubleDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBStringDoubleDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, double value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block(aKey, [aValue doubleValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictDoubleFieldSize([aValue doubleValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
+ WriteDictDoubleField(outputStream, [aValue doubleValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueDouble) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndValuesUsingBlock:^(NSString *key, double value, BOOL *stop) {
+ #pragma unused(stop)
+ block(key, [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
+ }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(double *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:key];
+ if (wrapped && value) {
+ *value = [wrapped doubleValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)addEntriesFromDictionary:(GPBStringDoubleDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setValue:(double)value forKey:(NSString *)key {
+ [_dictionary setObject:@(value) forKey:key];
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+ [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+@end
+
+#pragma mark - String -> Enum
+
+@implementation GPBStringEnumDictionary {
+ @package
+ NSMutableDictionary *_dictionary;
+ GPBEnumValidationFunc _validationFunc;
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValidationFunction:NULL
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [[[self alloc] initWithValidationFunction:func
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(NSString *)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringEnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:&rawValue
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringEnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:rawValues
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBStringEnumDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBStringEnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _dictionary = [[NSMutableDictionary alloc] init];
+ _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+ if (count && rawValues && keys) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ [_dictionary setObject:@(rawValues[i]) forKey:keys[i]];
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBStringEnumDictionary *)dictionary {
+ self = [self initWithValidationFunction:dictionary.validationFunc
+ rawValues:NULL
+ forKeys:NULL
+ count:0];
+ if (self) {
+ if (dictionary) {
+ [_dictionary addEntriesFromDictionary:dictionary->_dictionary];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_dictionary release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBStringEnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBStringEnumDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBStringEnumDictionary class]]) {
+ return NO;
+ }
+ return [_dictionary isEqual:other->_dictionary];
+}
+
+- (NSUInteger)hash {
+ return _dictionary.count;
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> { %@ }", [self class], self, _dictionary];
+}
+
+- (NSUInteger)count {
+ return _dictionary.count;
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(NSString *key, int32_t value, BOOL *stop))block {
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ block(aKey, [aValue intValue], stop);
+ }];
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ NSUInteger count = _dictionary.count;
+ if (count == 0) {
+ return 0;
+ }
+
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ __block size_t result = 0;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }];
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ GPBType keyType = field.mapKeyType;
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ #pragma unused(stop)
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictStringFieldSize(aKey, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize([aValue intValue], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictStringField(outputStream, aKey, kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, [aValue intValue], kMapValueFieldNumber, valueType);
+ }];
+}
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType {
+ size_t msgSize = ComputeDictStringFieldSize(key->valueString, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+ NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+ GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+ WriteDictStringField(outputStream, key->valueString, kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+ [outputStream release];
+ return data;
+}
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ [_dictionary setObject:@(value->valueEnum) forKey:key->valueString];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ [self enumerateKeysAndRawValuesUsingBlock:^(NSString *key, int32_t value, BOOL *stop) {
+ #pragma unused(stop)
+ block(key, @(value));
+ }];
+}
+
+- (BOOL)valueForKey:(NSString *)key value:(int32_t *)value {
+ NSNumber *wrapped = [_dictionary objectForKey:key];
+ if (wrapped && value) {
+ int32_t result = [wrapped intValue];
+ if (!_validationFunc(result)) {
+ result = kGPBUnrecognizedEnumeratorValue;
+ }
+ *value = result;
+ }
+ return (wrapped != NULL);
+}
+
+- (BOOL)valueForKey:(NSString *)key rawValue:(int32_t *)rawValue {
+ NSNumber *wrapped = [_dictionary objectForKey:key];
+ if (wrapped && rawValue) {
+ *rawValue = [wrapped intValue];
+ }
+ return (wrapped != NULL);
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(NSString *key, int32_t value, BOOL *stop))block {
+ GPBEnumValidationFunc func = _validationFunc;
+ [_dictionary enumerateKeysAndObjectsUsingBlock:^(NSString *aKey,
+ NSNumber *aValue,
+ BOOL *stop) {
+ int32_t unwrapped = [aValue intValue];
+ if (!func(unwrapped)) {
+ unwrapped = kGPBUnrecognizedEnumeratorValue;
+ }
+ block(aKey, unwrapped, stop);
+ }];
+}
+
+- (void)addRawEntriesFromDictionary:(GPBStringEnumDictionary *)otherDictionary {
+ if (otherDictionary) {
+ [_dictionary addEntriesFromDictionary:otherDictionary->_dictionary];
+ }
+}
+
+- (void)setRawValue:(int32_t)value forKey:(NSString *)key {
+ [_dictionary setObject:@(value) forKey:key];
+}
+
+- (void)removeValueForKey:(NSString *)aKey {
+ [_dictionary removeObjectForKey:aKey];
+}
+
+- (void)removeAll {
+ [_dictionary removeAllObjects];
+}
+
+- (void)setValue:(int32_t)value forKey:(NSString *)key {
+ if (!_validationFunc(value)) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"GPBStringEnumDictionary: Attempt to set an unknown enum value (%d)",
+ value];
+ }
+
+ [_dictionary setObject:@(value) forKey:key];
+}
+
+@end
+
+//%PDDM-EXPAND-END (5 expansions)
+
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt32, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> UInt32
+
+@implementation GPBBoolUInt32Dictionary {
+ @package
+ uint32_t _values[2];
+ BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint32_t)value
+ forKey:(BOOL)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolUInt32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolUInt32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolUInt32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolUInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ int idx = keys[i] ? 1 : 0;
+ _values[idx] = values[i];
+ _valueSet[idx] = YES;
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolUInt32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (dictionary->_valueSet[i]) {
+ _values[i] = dictionary->_values[i];
+ _valueSet[i] = YES;
+ }
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBBoolUInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolUInt32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBBoolUInt32Dictionary class]]) {
+ return NO;
+ }
+ if ((_valueSet[0] != other->_valueSet[0]) ||
+ (_valueSet[1] != other->_valueSet[1])) {
+ return NO;
+ }
+ if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+ (_valueSet[1] && (_values[1] != other->_values[1]))) {
+ return NO;
+ }
+ return YES;
+}
+
+- (NSUInteger)hash {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+ if (_valueSet[0]) {
+ [result appendFormat:@"NO: %u", _values[0]];
+ }
+ if (_valueSet[1]) {
+ [result appendFormat:@"YES: %u", _values[1]];
+ }
+ [result appendString:@" }"];
+ return result;
+}
+
+- (NSUInteger)count {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(uint32_t *)value {
+ int idx = (key ? 1 : 0);
+ if (_valueSet[idx]) {
+ if (value) {
+ *value = _values[idx];
+ }
+ return YES;
+ }
+ return NO;
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ int idx = (key->valueBool ? 1 : 0);
+ _values[idx] = value->valueUInt32;
+ _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ if (_valueSet[0]) {
+ block(@"false", [NSString stringWithFormat:@"%u", _values[0]]);
+ }
+ if (_valueSet[1]) {
+ block(@"true", [NSString stringWithFormat:@"%u", _values[1]]);
+ }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, uint32_t value, BOOL *stop))block {
+ BOOL stop = NO;
+ if (_valueSet[0]) {
+ block(NO, _values[0], &stop);
+ }
+ if (!stop && _valueSet[1]) {
+ block(YES, _values[1], &stop);
+ }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ NSUInteger count = 0;
+ size_t result = 0;
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ ++count;
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictUInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ WriteDictUInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+ }
+ }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolUInt32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (otherDictionary->_valueSet[i]) {
+ _valueSet[i] = YES;
+ _values[i] = otherDictionary->_values[i];
+ }
+ }
+ }
+}
+
+- (void)setValue:(uint32_t)value forKey:(BOOL)key {
+ int idx = (key ? 1 : 0);
+ _values[idx] = value;
+ _valueSet[idx] = YES;
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+ _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+ _valueSet[0] = NO;
+ _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int32, int32_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Int32
+
+@implementation GPBBoolInt32Dictionary {
+ @package
+ int32_t _values[2];
+ BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int32_t)value
+ forKey:(BOOL)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolInt32Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolInt32Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolInt32Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolInt32Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ int idx = keys[i] ? 1 : 0;
+ _values[idx] = values[i];
+ _valueSet[idx] = YES;
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolInt32Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (dictionary->_valueSet[i]) {
+ _values[i] = dictionary->_values[i];
+ _valueSet[i] = YES;
+ }
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBBoolInt32Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolInt32Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBBoolInt32Dictionary class]]) {
+ return NO;
+ }
+ if ((_valueSet[0] != other->_valueSet[0]) ||
+ (_valueSet[1] != other->_valueSet[1])) {
+ return NO;
+ }
+ if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+ (_valueSet[1] && (_values[1] != other->_values[1]))) {
+ return NO;
+ }
+ return YES;
+}
+
+- (NSUInteger)hash {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+ if (_valueSet[0]) {
+ [result appendFormat:@"NO: %d", _values[0]];
+ }
+ if (_valueSet[1]) {
+ [result appendFormat:@"YES: %d", _values[1]];
+ }
+ [result appendString:@" }"];
+ return result;
+}
+
+- (NSUInteger)count {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(int32_t *)value {
+ int idx = (key ? 1 : 0);
+ if (_valueSet[idx]) {
+ if (value) {
+ *value = _values[idx];
+ }
+ return YES;
+ }
+ return NO;
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ int idx = (key->valueBool ? 1 : 0);
+ _values[idx] = value->valueInt32;
+ _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ if (_valueSet[0]) {
+ block(@"false", [NSString stringWithFormat:@"%d", _values[0]]);
+ }
+ if (_valueSet[1]) {
+ block(@"true", [NSString stringWithFormat:@"%d", _values[1]]);
+ }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, int32_t value, BOOL *stop))block {
+ BOOL stop = NO;
+ if (_valueSet[0]) {
+ block(NO, _values[0], &stop);
+ }
+ if (!stop && _valueSet[1]) {
+ block(YES, _values[1], &stop);
+ }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ NSUInteger count = 0;
+ size_t result = 0;
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ ++count;
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+ }
+ }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolInt32Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (otherDictionary->_valueSet[i]) {
+ _valueSet[i] = YES;
+ _values[i] = otherDictionary->_values[i];
+ }
+ }
+ }
+}
+
+- (void)setValue:(int32_t)value forKey:(BOOL)key {
+ int idx = (key ? 1 : 0);
+ _values[idx] = value;
+ _valueSet[idx] = YES;
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+ _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+ _valueSet[0] = NO;
+ _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt64, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> UInt64
+
+@implementation GPBBoolUInt64Dictionary {
+ @package
+ uint64_t _values[2];
+ BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(uint64_t)value
+ forKey:(BOOL)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolUInt64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const uint64_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolUInt64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolUInt64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolUInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const uint64_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ int idx = keys[i] ? 1 : 0;
+ _values[idx] = values[i];
+ _valueSet[idx] = YES;
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolUInt64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (dictionary->_valueSet[i]) {
+ _values[i] = dictionary->_values[i];
+ _valueSet[i] = YES;
+ }
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBBoolUInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolUInt64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBBoolUInt64Dictionary class]]) {
+ return NO;
+ }
+ if ((_valueSet[0] != other->_valueSet[0]) ||
+ (_valueSet[1] != other->_valueSet[1])) {
+ return NO;
+ }
+ if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+ (_valueSet[1] && (_values[1] != other->_values[1]))) {
+ return NO;
+ }
+ return YES;
+}
+
+- (NSUInteger)hash {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+ if (_valueSet[0]) {
+ [result appendFormat:@"NO: %llu", _values[0]];
+ }
+ if (_valueSet[1]) {
+ [result appendFormat:@"YES: %llu", _values[1]];
+ }
+ [result appendString:@" }"];
+ return result;
+}
+
+- (NSUInteger)count {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(uint64_t *)value {
+ int idx = (key ? 1 : 0);
+ if (_valueSet[idx]) {
+ if (value) {
+ *value = _values[idx];
+ }
+ return YES;
+ }
+ return NO;
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ int idx = (key->valueBool ? 1 : 0);
+ _values[idx] = value->valueUInt64;
+ _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ if (_valueSet[0]) {
+ block(@"false", [NSString stringWithFormat:@"%llu", _values[0]]);
+ }
+ if (_valueSet[1]) {
+ block(@"true", [NSString stringWithFormat:@"%llu", _values[1]]);
+ }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, uint64_t value, BOOL *stop))block {
+ BOOL stop = NO;
+ if (_valueSet[0]) {
+ block(NO, _values[0], &stop);
+ }
+ if (!stop && _valueSet[1]) {
+ block(YES, _values[1], &stop);
+ }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ NSUInteger count = 0;
+ size_t result = 0;
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ ++count;
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictUInt64FieldSize(_values[i], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ WriteDictUInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+ }
+ }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolUInt64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (otherDictionary->_valueSet[i]) {
+ _valueSet[i] = YES;
+ _values[i] = otherDictionary->_values[i];
+ }
+ }
+ }
+}
+
+- (void)setValue:(uint64_t)value forKey:(BOOL)key {
+ int idx = (key ? 1 : 0);
+ _values[idx] = value;
+ _valueSet[idx] = YES;
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+ _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+ _valueSet[0] = NO;
+ _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int64, int64_t)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Int64
+
+@implementation GPBBoolInt64Dictionary {
+ @package
+ int64_t _values[2];
+ BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(int64_t)value
+ forKey:(BOOL)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolInt64Dictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const int64_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolInt64Dictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolInt64Dictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolInt64Dictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const int64_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ int idx = keys[i] ? 1 : 0;
+ _values[idx] = values[i];
+ _valueSet[idx] = YES;
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolInt64Dictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (dictionary->_valueSet[i]) {
+ _values[i] = dictionary->_values[i];
+ _valueSet[i] = YES;
+ }
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBBoolInt64Dictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolInt64Dictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBBoolInt64Dictionary class]]) {
+ return NO;
+ }
+ if ((_valueSet[0] != other->_valueSet[0]) ||
+ (_valueSet[1] != other->_valueSet[1])) {
+ return NO;
+ }
+ if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+ (_valueSet[1] && (_values[1] != other->_values[1]))) {
+ return NO;
+ }
+ return YES;
+}
+
+- (NSUInteger)hash {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+ if (_valueSet[0]) {
+ [result appendFormat:@"NO: %lld", _values[0]];
+ }
+ if (_valueSet[1]) {
+ [result appendFormat:@"YES: %lld", _values[1]];
+ }
+ [result appendString:@" }"];
+ return result;
+}
+
+- (NSUInteger)count {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(int64_t *)value {
+ int idx = (key ? 1 : 0);
+ if (_valueSet[idx]) {
+ if (value) {
+ *value = _values[idx];
+ }
+ return YES;
+ }
+ return NO;
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ int idx = (key->valueBool ? 1 : 0);
+ _values[idx] = value->valueInt64;
+ _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ if (_valueSet[0]) {
+ block(@"false", [NSString stringWithFormat:@"%lld", _values[0]]);
+ }
+ if (_valueSet[1]) {
+ block(@"true", [NSString stringWithFormat:@"%lld", _values[1]]);
+ }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, int64_t value, BOOL *stop))block {
+ BOOL stop = NO;
+ if (_valueSet[0]) {
+ block(NO, _values[0], &stop);
+ }
+ if (!stop && _valueSet[1]) {
+ block(YES, _values[1], &stop);
+ }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ NSUInteger count = 0;
+ size_t result = 0;
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ ++count;
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictInt64FieldSize(_values[i], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ WriteDictInt64Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+ }
+ }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolInt64Dictionary *)otherDictionary {
+ if (otherDictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (otherDictionary->_valueSet[i]) {
+ _valueSet[i] = YES;
+ _values[i] = otherDictionary->_values[i];
+ }
+ }
+ }
+}
+
+- (void)setValue:(int64_t)value forKey:(BOOL)key {
+ int idx = (key ? 1 : 0);
+ _values[idx] = value;
+ _valueSet[idx] = YES;
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+ _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+ _valueSet[0] = NO;
+ _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Bool, BOOL)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Bool
+
+@implementation GPBBoolBoolDictionary {
+ @package
+ BOOL _values[2];
+ BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(BOOL)value
+ forKey:(BOOL)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolBoolDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const BOOL [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolBoolDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolBoolDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolBoolDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const BOOL [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ int idx = keys[i] ? 1 : 0;
+ _values[idx] = values[i];
+ _valueSet[idx] = YES;
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolBoolDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (dictionary->_valueSet[i]) {
+ _values[i] = dictionary->_values[i];
+ _valueSet[i] = YES;
+ }
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBBoolBoolDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolBoolDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBBoolBoolDictionary class]]) {
+ return NO;
+ }
+ if ((_valueSet[0] != other->_valueSet[0]) ||
+ (_valueSet[1] != other->_valueSet[1])) {
+ return NO;
+ }
+ if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+ (_valueSet[1] && (_values[1] != other->_values[1]))) {
+ return NO;
+ }
+ return YES;
+}
+
+- (NSUInteger)hash {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+ if (_valueSet[0]) {
+ [result appendFormat:@"NO: %d", _values[0]];
+ }
+ if (_valueSet[1]) {
+ [result appendFormat:@"YES: %d", _values[1]];
+ }
+ [result appendString:@" }"];
+ return result;
+}
+
+- (NSUInteger)count {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(BOOL *)value {
+ int idx = (key ? 1 : 0);
+ if (_valueSet[idx]) {
+ if (value) {
+ *value = _values[idx];
+ }
+ return YES;
+ }
+ return NO;
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ int idx = (key->valueBool ? 1 : 0);
+ _values[idx] = value->valueBool;
+ _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ if (_valueSet[0]) {
+ block(@"false", (_values[0] ? @"true" : @"false"));
+ }
+ if (_valueSet[1]) {
+ block(@"true", (_values[1] ? @"true" : @"false"));
+ }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, BOOL value, BOOL *stop))block {
+ BOOL stop = NO;
+ if (_valueSet[0]) {
+ block(NO, _values[0], &stop);
+ }
+ if (!stop && _valueSet[1]) {
+ block(YES, _values[1], &stop);
+ }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ NSUInteger count = 0;
+ size_t result = 0;
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ ++count;
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictBoolFieldSize(_values[i], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ WriteDictBoolField(outputStream, _values[i], kMapValueFieldNumber, valueType);
+ }
+ }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolBoolDictionary *)otherDictionary {
+ if (otherDictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (otherDictionary->_valueSet[i]) {
+ _valueSet[i] = YES;
+ _values[i] = otherDictionary->_values[i];
+ }
+ }
+ }
+}
+
+- (void)setValue:(BOOL)value forKey:(BOOL)key {
+ int idx = (key ? 1 : 0);
+ _values[idx] = value;
+ _valueSet[idx] = YES;
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+ _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+ _valueSet[0] = NO;
+ _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Float, float)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Float
+
+@implementation GPBBoolFloatDictionary {
+ @package
+ float _values[2];
+ BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(float)value
+ forKey:(BOOL)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolFloatDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const float [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolFloatDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolFloatDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolFloatDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const float [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ int idx = keys[i] ? 1 : 0;
+ _values[idx] = values[i];
+ _valueSet[idx] = YES;
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolFloatDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (dictionary->_valueSet[i]) {
+ _values[i] = dictionary->_values[i];
+ _valueSet[i] = YES;
+ }
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBBoolFloatDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolFloatDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBBoolFloatDictionary class]]) {
+ return NO;
+ }
+ if ((_valueSet[0] != other->_valueSet[0]) ||
+ (_valueSet[1] != other->_valueSet[1])) {
+ return NO;
+ }
+ if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+ (_valueSet[1] && (_values[1] != other->_values[1]))) {
+ return NO;
+ }
+ return YES;
+}
+
+- (NSUInteger)hash {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+ if (_valueSet[0]) {
+ [result appendFormat:@"NO: %f", _values[0]];
+ }
+ if (_valueSet[1]) {
+ [result appendFormat:@"YES: %f", _values[1]];
+ }
+ [result appendString:@" }"];
+ return result;
+}
+
+- (NSUInteger)count {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(float *)value {
+ int idx = (key ? 1 : 0);
+ if (_valueSet[idx]) {
+ if (value) {
+ *value = _values[idx];
+ }
+ return YES;
+ }
+ return NO;
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ int idx = (key->valueBool ? 1 : 0);
+ _values[idx] = value->valueFloat;
+ _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ if (_valueSet[0]) {
+ block(@"false", [NSString stringWithFormat:@"%.*g", FLT_DIG, _values[0]]);
+ }
+ if (_valueSet[1]) {
+ block(@"true", [NSString stringWithFormat:@"%.*g", FLT_DIG, _values[1]]);
+ }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, float value, BOOL *stop))block {
+ BOOL stop = NO;
+ if (_valueSet[0]) {
+ block(NO, _values[0], &stop);
+ }
+ if (!stop && _valueSet[1]) {
+ block(YES, _values[1], &stop);
+ }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ NSUInteger count = 0;
+ size_t result = 0;
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ ++count;
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictFloatFieldSize(_values[i], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ WriteDictFloatField(outputStream, _values[i], kMapValueFieldNumber, valueType);
+ }
+ }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolFloatDictionary *)otherDictionary {
+ if (otherDictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (otherDictionary->_valueSet[i]) {
+ _valueSet[i] = YES;
+ _values[i] = otherDictionary->_values[i];
+ }
+ }
+ }
+}
+
+- (void)setValue:(float)value forKey:(BOOL)key {
+ int idx = (key ? 1 : 0);
+ _values[idx] = value;
+ _valueSet[idx] = YES;
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+ _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+ _valueSet[0] = NO;
+ _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Double, double)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Double
+
+@implementation GPBBoolDoubleDictionary {
+ @package
+ double _values[2];
+ BOOL _valueSet[2];
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(double)value
+ forKey:(BOOL)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolDoubleDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const double [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolDoubleDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolDoubleDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolDoubleDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const double [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ int idx = keys[i] ? 1 : 0;
+ _values[idx] = values[i];
+ _valueSet[idx] = YES;
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolDoubleDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (dictionary->_valueSet[i]) {
+ _values[i] = dictionary->_values[i];
+ _valueSet[i] = YES;
+ }
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBBoolDoubleDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolDoubleDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBBoolDoubleDictionary class]]) {
+ return NO;
+ }
+ if ((_valueSet[0] != other->_valueSet[0]) ||
+ (_valueSet[1] != other->_valueSet[1])) {
+ return NO;
+ }
+ if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+ (_valueSet[1] && (_values[1] != other->_values[1]))) {
+ return NO;
+ }
+ return YES;
+}
+
+- (NSUInteger)hash {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+ if (_valueSet[0]) {
+ [result appendFormat:@"NO: %lf", _values[0]];
+ }
+ if (_valueSet[1]) {
+ [result appendFormat:@"YES: %lf", _values[1]];
+ }
+ [result appendString:@" }"];
+ return result;
+}
+
+- (NSUInteger)count {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(double *)value {
+ int idx = (key ? 1 : 0);
+ if (_valueSet[idx]) {
+ if (value) {
+ *value = _values[idx];
+ }
+ return YES;
+ }
+ return NO;
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ int idx = (key->valueBool ? 1 : 0);
+ _values[idx] = value->valueDouble;
+ _valueSet[idx] = YES;
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ if (_valueSet[0]) {
+ block(@"false", [NSString stringWithFormat:@"%.*lg", DBL_DIG, _values[0]]);
+ }
+ if (_valueSet[1]) {
+ block(@"true", [NSString stringWithFormat:@"%.*lg", DBL_DIG, _values[1]]);
+ }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, double value, BOOL *stop))block {
+ BOOL stop = NO;
+ if (_valueSet[0]) {
+ block(NO, _values[0], &stop);
+ }
+ if (!stop && _valueSet[1]) {
+ block(YES, _values[1], &stop);
+ }
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ NSUInteger count = 0;
+ size_t result = 0;
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ ++count;
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictDoubleFieldSize(_values[i], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ WriteDictDoubleField(outputStream, _values[i], kMapValueFieldNumber, valueType);
+ }
+ }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolDoubleDictionary *)otherDictionary {
+ if (otherDictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (otherDictionary->_valueSet[i]) {
+ _valueSet[i] = YES;
+ _values[i] = otherDictionary->_values[i];
+ }
+ }
+ }
+}
+
+- (void)setValue:(double)value forKey:(BOOL)key {
+ int idx = (key ? 1 : 0);
+ _values[idx] = value;
+ _valueSet[idx] = YES;
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+ _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+ _valueSet[0] = NO;
+ _valueSet[1] = NO;
+}
+
+@end
+
+//%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_OBJECT_IMPL(Object, id)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Object
+
+@implementation GPBBoolObjectDictionary {
+ @package
+ id _values[2];
+}
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValues:NULL forKeys:NULL count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValue:(id)value
+ forKey:(BOOL)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolObjectDictionary*)[self alloc] initWithValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValues:(const id [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolObjectDictionary*)[self alloc] initWithValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolObjectDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolObjectDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithCapacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithCapacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValues:(const id [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ for (NSUInteger i = 0; i < count; ++i) {
+ int idx = keys[i] ? 1 : 0;
+ [_values[idx] release];
+ _values[idx] = (id)[values[i] retain];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolObjectDictionary *)dictionary {
+ self = [self initWithValues:NULL forKeys:NULL count:0];
+ if (self) {
+ if (dictionary) {
+ _values[0] = [dictionary->_values[0] retain];
+ _values[1] = [dictionary->_values[1] retain];
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithCapacity:(NSUInteger)numItems {
+ #pragma unused(numItems)
+ return [self initWithValues:NULL forKeys:NULL count:0];
+}
+
+- (void)dealloc {
+ [_values[0] release];
+ [_values[1] release];
+ [super dealloc];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBBoolObjectDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolObjectDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBBoolObjectDictionary class]]) {
+ return NO;
+ }
+ if (((_values[0] != nil) != (other->_values[0] != nil)) ||
+ ((_values[1] != nil) != (other->_values[1] != nil))) {
+ return NO;
+ }
+ if (((_values[0] != nil) && (![_values[0] isEqual:other->_values[0]])) ||
+ ((_values[1] != nil) && (![_values[1] isEqual:other->_values[1]]))) {
+ return NO;
+ }
+ return YES;
+}
+
+- (NSUInteger)hash {
+ return ((_values[0] != nil) ? 1 : 0) + ((_values[1] != nil) ? 1 : 0);
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+ if ((_values[0] != nil)) {
+ [result appendFormat:@"NO: %@", _values[0]];
+ }
+ if ((_values[1] != nil)) {
+ [result appendFormat:@"YES: %@", _values[1]];
+ }
+ [result appendString:@" }"];
+ return result;
+}
+
+- (NSUInteger)count {
+ return ((_values[0] != nil) ? 1 : 0) + ((_values[1] != nil) ? 1 : 0);
+}
+
+- (id)valueForKey:(BOOL)key {
+ return _values[key ? 1 : 0];
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ int idx = (key->valueBool ? 1 : 0);
+ [_values[idx] release];
+ _values[idx] = [value->valueString retain];
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ if (_values[0] != nil) {
+ block(@"false", _values[0]);
+ }
+ if ((_values[1] != nil)) {
+ block(@"true", _values[1]);
+ }
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, id value, BOOL *stop))block {
+ BOOL stop = NO;
+ if (_values[0] != nil) {
+ block(NO, _values[0], &stop);
+ }
+ if (!stop && (_values[1] != nil)) {
+ block(YES, _values[1], &stop);
+ }
+}
+
+- (BOOL)isInitialized {
+ if (_values[0] && ![_values[0] isInitialized]) {
+ return NO;
+ }
+ if (_values[1] && ![_values[1] isInitialized]) {
+ return NO;
+ }
+ return YES;
+}
+
+- (instancetype)deepCopyWithZone:(NSZone *)zone {
+ GPBBoolObjectDictionary *newDict =
+ [[GPBBoolObjectDictionary alloc] init];
+ for (int i = 0; i < 2; ++i) {
+ if (_values[i] != nil) {
+ newDict->_values[i] = [_values[i] copyWithZone:zone];
+ }
+ }
+ return newDict;
+}
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ NSUInteger count = 0;
+ size_t result = 0;
+ for (int i = 0; i < 2; ++i) {
+ if (_values[i] != nil) {
+ ++count;
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ for (int i = 0; i < 2; ++i) {
+ if (_values[i] != nil) {
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictObjectFieldSize(_values[i], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ WriteDictObjectField(outputStream, _values[i], kMapValueFieldNumber, valueType);
+ }
+ }
+}
+
+- (void)addEntriesFromDictionary:(GPBBoolObjectDictionary *)otherDictionary {
+ if (otherDictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (otherDictionary->_values[i] != nil) {
+ [_values[i] release];
+ _values[i] = [otherDictionary->_values[i] retain];
+ }
+ }
+ }
+}
+
+- (void)setValue:(id)value forKey:(BOOL)key {
+ int idx = (key ? 1 : 0);
+ [_values[idx] release];
+ _values[idx] = [value retain];
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+ int idx = (aKey ? 1 : 0);
+ [_values[idx] release];
+ _values[idx] = nil;
+}
+
+- (void)removeAll {
+ for (int i = 0; i < 2; ++i) {
+ [_values[i] release];
+ _values[i] = nil;
+ }
+}
+
+@end
+
+//%PDDM-EXPAND-END (8 expansions)
+
+#pragma mark - Bool -> Enum
+
+@implementation GPBBoolEnumDictionary {
+ @package
+ GPBEnumValidationFunc _validationFunc;
+ int32_t _values[2];
+ BOOL _valueSet[2];
+}
+
+@synthesize validationFunc = _validationFunc;
+
++ (instancetype)dictionary {
+ return [[[self alloc] initWithValidationFunction:NULL
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [[[self alloc] initWithValidationFunction:func
+ rawValues:NULL
+ forKeys:NULL
+ count:0] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValue:(int32_t)rawValue
+ forKey:(BOOL)key {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolEnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:&rawValue
+ forKeys:&key
+ count:1] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])values
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolEnumDictionary*)[self alloc] initWithValidationFunction:func
+ rawValues:values
+ forKeys:keys
+ count:count] autorelease];
+}
+
++ (instancetype)dictionaryWithDictionary:(GPBBoolEnumDictionary *)dictionary {
+ // Cast is needed so the compiler knows what class we are invoking initWithValues:forKeys:count:
+ // on to get the type correct.
+ return [[(GPBBoolEnumDictionary*)[self alloc] initWithDictionary:dictionary] autorelease];
+}
+
++ (instancetype)dictionaryWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+ return [[[self alloc] initWithValidationFunction:func capacity:numItems] autorelease];
+}
+
+- (instancetype)init {
+ return [self initWithValidationFunction:NULL rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func {
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ rawValues:(const int32_t [])rawValues
+ forKeys:(const BOOL [])keys
+ count:(NSUInteger)count {
+ self = [super init];
+ if (self) {
+ _validationFunc = (func != NULL ? func : DictDefault_IsValidValue);
+ for (NSUInteger i = 0; i < count; ++i) {
+ int idx = keys[i] ? 1 : 0;
+ _values[idx] = rawValues[i];
+ _valueSet[idx] = YES;
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithDictionary:(GPBBoolEnumDictionary *)dictionary {
+ self = [self initWithValidationFunction:dictionary.validationFunc
+ rawValues:NULL
+ forKeys:NULL
+ count:0];
+ if (self) {
+ if (dictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (dictionary->_valueSet[i]) {
+ _values[i] = dictionary->_values[i];
+ _valueSet[i] = YES;
+ }
+ }
+ }
+ }
+ return self;
+}
+
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
+ capacity:(NSUInteger)numItems {
+#pragma unused(numItems)
+ return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
+}
+
+- (instancetype)copyWithZone:(NSZone *)zone {
+ return [[GPBBoolEnumDictionary allocWithZone:zone] initWithDictionary:self];
+}
+
+- (BOOL)isEqual:(GPBBoolEnumDictionary *)other {
+ if (self == other) {
+ return YES;
+ }
+ if (![other isKindOfClass:[GPBBoolEnumDictionary class]]) {
+ return NO;
+ }
+ if ((_valueSet[0] != other->_valueSet[0]) ||
+ (_valueSet[1] != other->_valueSet[1])) {
+ return NO;
+ }
+ if ((_valueSet[0] && (_values[0] != other->_values[0])) ||
+ (_valueSet[1] && (_values[1] != other->_values[1]))) {
+ return NO;
+ }
+ return YES;
+}
+
+- (NSUInteger)hash {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (NSString *)description {
+ NSMutableString *result = [NSMutableString stringWithFormat:@"<%@ %p> {", [self class], self];
+ if (_valueSet[0]) {
+ [result appendFormat:@"NO: %d", _values[0]];
+ }
+ if (_valueSet[1]) {
+ [result appendFormat:@"YES: %d", _values[1]];
+ }
+ [result appendString:@" }"];
+ return result;
+}
+
+- (NSUInteger)count {
+ return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
+}
+
+- (BOOL)valueForKey:(BOOL)key value:(int32_t*)value {
+ int idx = (key ? 1 : 0);
+ if (_valueSet[idx]) {
+ if (value) {
+ int32_t result = _values[idx];
+ if (!_validationFunc(result)) {
+ result = kGPBUnrecognizedEnumeratorValue;
+ }
+ *value = result;
+ }
+ return YES;
+ }
+ return NO;
+}
+
+- (BOOL)valueForKey:(BOOL)key rawValue:(int32_t*)rawValue {
+ int idx = (key ? 1 : 0);
+ if (_valueSet[idx]) {
+ if (rawValue) {
+ *rawValue = _values[idx];
+ }
+ return YES;
+ }
+ return NO;
+}
+
+- (void)enumerateKeysAndValuesUsingBlock:
+ (void (^)(BOOL key, int32_t value, BOOL *stop))block {
+ BOOL stop = NO;
+ if (_valueSet[0]) {
+ block(NO, _values[0], &stop);
+ }
+ if (!stop && _valueSet[1]) {
+ block(YES, _values[1], &stop);
+ }
+}
+
+- (void)enumerateKeysAndRawValuesUsingBlock:
+ (void (^)(BOOL key, int32_t rawValue, BOOL *stop))block {
+ BOOL stop = NO;
+ GPBEnumValidationFunc func = _validationFunc;
+ int32_t validatedValue;
+ if (_valueSet[0]) {
+ validatedValue = _values[0];
+ if (!func(validatedValue)) {
+ validatedValue = kGPBUnrecognizedEnumeratorValue;
+ }
+ block(NO, validatedValue, &stop);
+ }
+ if (!stop && _valueSet[1]) {
+ validatedValue = _values[1];
+ if (!func(validatedValue)) {
+ validatedValue = kGPBUnrecognizedEnumeratorValue;
+ }
+ block(YES, validatedValue, &stop);
+ }
+}
+
+//%PDDM-EXPAND SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool)
+// This block of code is generated, do not edit it directly.
+
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType {
+ size_t msgSize = ComputeDictBoolFieldSize(key->valueBool, kMapKeyFieldNumber, keyType);
+ msgSize += ComputeDictEnumFieldSize(value, kMapValueFieldNumber, GPBTypeEnum);
+ NSMutableData *data = [NSMutableData dataWithLength:msgSize];
+ GPBCodedOutputStream *outputStream = [[GPBCodedOutputStream alloc] initWithData:data];
+ WriteDictBoolField(outputStream, key->valueBool, kMapKeyFieldNumber, keyType);
+ WriteDictEnumField(outputStream, value, kMapValueFieldNumber, GPBTypeEnum);
+ [outputStream release];
+ return data;
+}
+
+//%PDDM-EXPAND-END SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool)
+
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ NSUInteger count = 0;
+ size_t result = 0;
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ ++count;
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+ result += GPBComputeRawVarint32SizeForInteger(msgSize) + msgSize;
+ }
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field), GPBTypeMessage);
+ result += tagSize * count;
+ return result;
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field {
+ GPBType valueType = GPBGetFieldType(field);
+ uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
+ for (int i = 0; i < 2; ++i) {
+ if (_valueSet[i]) {
+ // Write the tag.
+ [outputStream writeInt32NoTag:tag];
+ // Write the size of the message.
+ size_t msgSize = ComputeDictBoolFieldSize((i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ msgSize += ComputeDictInt32FieldSize(_values[i], kMapValueFieldNumber, valueType);
+ [outputStream writeInt32NoTag:(int32_t)msgSize];
+ // Write the fields.
+ WriteDictBoolField(outputStream, (i == 1), kMapKeyFieldNumber, GPBTypeBool);
+ WriteDictInt32Field(outputStream, _values[i], kMapValueFieldNumber, valueType);
+ }
+ }
+}
+
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block {
+ if (_valueSet[0]) {
+ block(@"false", @(_values[0]));
+ }
+ if (_valueSet[1]) {
+ block(@"true", @(_values[1]));
+ }
+}
+
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key {
+ int idx = (key->valueBool ? 1 : 0);
+ _values[idx] = value->valueInt32;
+ _valueSet[idx] = YES;
+}
+
+- (void)addRawEntriesFromDictionary:(GPBBoolEnumDictionary *)otherDictionary {
+ if (otherDictionary) {
+ for (int i = 0; i < 2; ++i) {
+ if (otherDictionary->_valueSet[i]) {
+ _valueSet[i] = YES;
+ _values[i] = otherDictionary->_values[i];
+ }
+ }
+ }
+}
+
+- (void)setValue:(int32_t)value forKey:(BOOL)key {
+ if (!_validationFunc(value)) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"GPBBoolEnumDictionary: Attempt to set an unknown enum value (%d)",
+ value];
+ }
+ int idx = (key ? 1 : 0);
+ _values[idx] = value;
+ _valueSet[idx] = YES;
+}
+
+- (void)setRawValue:(int32_t)rawValue forKey:(BOOL)key {
+ int idx = (key ? 1 : 0);
+ _values[idx] = rawValue;
+ _valueSet[idx] = YES;
+}
+
+- (void)removeValueForKey:(BOOL)aKey {
+ _valueSet[aKey ? 1 : 0] = NO;
+}
+
+- (void)removeAll {
+ _valueSet[0] = NO;
+ _valueSet[1] = NO;
+}
+
+@end
diff --git a/objectivec/GPBDictionary_PackagePrivate.h b/objectivec/GPBDictionary_PackagePrivate.h
new file mode 100644
index 00000000..54b37dd8
--- /dev/null
+++ b/objectivec/GPBDictionary_PackagePrivate.h
@@ -0,0 +1,577 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBDictionary.h"
+
+@class GPBCodedInputStream;
+@class GPBCodedOutputStream;
+@class GPBExtensionRegistry;
+@class GPBFieldDescriptor;
+
+//%PDDM-DEFINE DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(KEY_NAME)
+//%DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(KEY_NAME)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Object, Object)
+//%PDDM-DEFINE DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(KEY_NAME)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, UInt32, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Int32, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, UInt64, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Int64, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Bool, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Float, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Double, Basic)
+//%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Enum, Enum)
+
+//%PDDM-DEFINE DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, VALUE_NAME, HELPER)
+//%@interface GPB##KEY_NAME##VALUE_NAME##Dictionary ()
+//%- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+//%- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+//% asField:(GPBFieldDescriptor *)field;
+//%- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+//%- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+//%EXTRA_DICTIONARY_PRIVATE_INTERFACES_##HELPER()@end
+//%
+
+//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Basic()
+// Empty
+//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Object()
+//%- (BOOL)isInitialized;
+//%- (instancetype)deepCopyWithZone:(NSZone *)zone
+//% __attribute__((ns_returns_retained));
+//%
+//%PDDM-DEFINE EXTRA_DICTIONARY_PRIVATE_INTERFACES_Enum()
+//%- (NSData *)serializedDataForUnknownValue:(int32_t)value
+//% forKey:(GPBValue *)key
+//% keyType:(GPBType)keyType;
+//%
+
+//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt32)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBUInt32UInt32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt32Int32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt32UInt64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt32Int64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt32BoolDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt32FloatDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt32DoubleDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt32EnumDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType;
+@end
+
+@interface GPBUInt32ObjectDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (BOOL)isInitialized;
+- (instancetype)deepCopyWithZone:(NSZone *)zone
+ __attribute__((ns_returns_retained));
+@end
+
+//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int32)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBInt32UInt32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt32Int32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt32UInt64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt32Int64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt32BoolDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt32FloatDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt32DoubleDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt32EnumDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType;
+@end
+
+@interface GPBInt32ObjectDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (BOOL)isInitialized;
+- (instancetype)deepCopyWithZone:(NSZone *)zone
+ __attribute__((ns_returns_retained));
+@end
+
+//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt64)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBUInt64UInt32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt64Int32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt64UInt64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt64Int64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt64BoolDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt64FloatDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt64DoubleDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBUInt64EnumDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType;
+@end
+
+@interface GPBUInt64ObjectDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (BOOL)isInitialized;
+- (instancetype)deepCopyWithZone:(NSZone *)zone
+ __attribute__((ns_returns_retained));
+@end
+
+//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int64)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBInt64UInt32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt64Int32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt64UInt64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt64Int64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt64BoolDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt64FloatDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt64DoubleDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBInt64EnumDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType;
+@end
+
+@interface GPBInt64ObjectDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (BOOL)isInitialized;
+- (instancetype)deepCopyWithZone:(NSZone *)zone
+ __attribute__((ns_returns_retained));
+@end
+
+//%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Bool)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBBoolUInt32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBBoolInt32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBBoolUInt64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBBoolInt64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBBoolBoolDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBBoolFloatDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBBoolDoubleDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBBoolEnumDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType;
+@end
+
+@interface GPBBoolObjectDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (BOOL)isInitialized;
+- (instancetype)deepCopyWithZone:(NSZone *)zone
+ __attribute__((ns_returns_retained));
+@end
+
+//%PDDM-EXPAND DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(String)
+// This block of code is generated, do not edit it directly.
+
+@interface GPBStringUInt32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBStringInt32Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBStringUInt64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBStringInt64Dictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBStringBoolDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBStringFloatDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBStringDoubleDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+@end
+
+@interface GPBStringEnumDictionary ()
+- (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
+ asField:(GPBFieldDescriptor *)field;
+- (void)setGPBValue:(GPBValue *)value forGPBValueKey:(GPBValue *)key;
+- (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
+- (NSData *)serializedDataForUnknownValue:(int32_t)value
+ forKey:(GPBValue *)key
+ keyType:(GPBType)keyType;
+@end
+
+//%PDDM-EXPAND-END (6 expansions)
+
+CF_EXTERN_C_BEGIN
+
+// Helper to compute size when an NSDictionary is used for the map instead
+// of a custom type.
+size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict,
+ GPBFieldDescriptor *field);
+
+// Helper to write out when an NSDictionary is used for the map instead
+// of a custom type.
+void GPBDictionaryWriteToStreamInternalHelper(
+ GPBCodedOutputStream *outputStream, NSDictionary *dict,
+ GPBFieldDescriptor *field);
+
+// Helper to check message initialization when an NSDictionary is used for
+// the map instead of a custom type.
+BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict,
+ GPBFieldDescriptor *field);
+
+// Helper to read a map instead.
+void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
+ GPBExtensionRegistry *registry,
+ GPBFieldDescriptor *field,
+ GPBMessage *parentMessage);
+
+CF_EXTERN_C_END
diff --git a/objectivec/GPBExtensionField.h b/objectivec/GPBExtensionField.h
new file mode 100644
index 00000000..e5ba1561
--- /dev/null
+++ b/objectivec/GPBExtensionField.h
@@ -0,0 +1,51 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBWireFormat.h"
+#import "GPBTypes.h"
+
+@class GPBCodedInputStream;
+@class GPBCodedOutputStream;
+@class GPBExtensionRegistry;
+@class GPBDescriptor;
+@class GPBExtensionDescriptor;
+
+@interface GPBExtensionField : NSObject<NSCopying>
+
+@property(nonatomic, readonly) int32_t fieldNumber;
+@property(nonatomic, readonly) GPBWireFormat wireType;
+@property(nonatomic, readonly) BOOL isRepeated;
+@property(nonatomic, readonly) GPBDescriptor *containingType;
+@property(nonatomic, readonly) id defaultValue;
+@property(nonatomic, readonly) GPBExtensionDescriptor *descriptor;
+
+@end
diff --git a/objectivec/GPBExtensionField.m b/objectivec/GPBExtensionField.m
new file mode 100644
index 00000000..bbb36d7f
--- /dev/null
+++ b/objectivec/GPBExtensionField.m
@@ -0,0 +1,525 @@
+// 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 "GPBExtensionField_PackagePrivate.h"
+
+#import <objc/runtime.h>
+
+#import "GPBCodedInputStream_PackagePrivate.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+GPB_INLINE size_t TypeSize(GPBType type) {
+ switch (type) {
+ case GPBTypeBool:
+ return 1;
+ case GPBTypeFixed32:
+ case GPBTypeSFixed32:
+ case GPBTypeFloat:
+ return 4;
+ case GPBTypeFixed64:
+ case GPBTypeSFixed64:
+ case GPBTypeDouble:
+ return 8;
+ default:
+ return 0;
+ }
+}
+
+GPB_INLINE BOOL ExtensionIsRepeated(GPBExtensionDescription *description) {
+ return (description->options & GPBExtensionRepeated) != 0;
+}
+
+GPB_INLINE BOOL ExtensionIsPacked(GPBExtensionDescription *description) {
+ return (description->options & GPBExtensionPacked) != 0;
+}
+
+GPB_INLINE BOOL ExtensionIsWireFormat(GPBExtensionDescription *description) {
+ return (description->options & GPBExtensionSetWireFormat) != 0;
+}
+
+static size_t ComputePBSerializedSizeNoTagOfObject(GPBType type, id object) {
+#define FIELD_CASE(TYPE, ACCESSOR) \
+ case GPBType##TYPE: \
+ return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]);
+#define FIELD_CASE2(TYPE) \
+ case GPBType##TYPE: \
+ return GPBCompute##TYPE##SizeNoTag(object);
+ switch (type) {
+ FIELD_CASE(Bool, boolValue)
+ FIELD_CASE(Float, floatValue)
+ FIELD_CASE(Double, doubleValue)
+ FIELD_CASE(Int32, intValue)
+ FIELD_CASE(SFixed32, intValue)
+ FIELD_CASE(SInt32, intValue)
+ FIELD_CASE(Enum, intValue)
+ FIELD_CASE(Int64, longLongValue)
+ FIELD_CASE(SInt64, longLongValue)
+ FIELD_CASE(SFixed64, longLongValue)
+ FIELD_CASE(UInt32, unsignedIntValue)
+ FIELD_CASE(Fixed32, unsignedIntValue)
+ FIELD_CASE(UInt64, unsignedLongLongValue)
+ FIELD_CASE(Fixed64, unsignedLongLongValue)
+ FIELD_CASE2(Data)
+ FIELD_CASE2(String)
+ FIELD_CASE2(Message)
+ FIELD_CASE2(Group)
+ }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static size_t ComputeSerializedSizeIncludingTagOfObject(
+ GPBExtensionDescription *description, id object) {
+#define FIELD_CASE(TYPE, ACCESSOR) \
+ case GPBType##TYPE: \
+ return GPBCompute##TYPE##Size(description->fieldNumber, \
+ [(NSNumber *)object ACCESSOR]);
+#define FIELD_CASE2(TYPE) \
+ case GPBType##TYPE: \
+ return GPBCompute##TYPE##Size(description->fieldNumber, object);
+ switch (description->type) {
+ FIELD_CASE(Bool, boolValue)
+ FIELD_CASE(Float, floatValue)
+ FIELD_CASE(Double, doubleValue)
+ FIELD_CASE(Int32, intValue)
+ FIELD_CASE(SFixed32, intValue)
+ FIELD_CASE(SInt32, intValue)
+ FIELD_CASE(Enum, intValue)
+ FIELD_CASE(Int64, longLongValue)
+ FIELD_CASE(SInt64, longLongValue)
+ FIELD_CASE(SFixed64, longLongValue)
+ FIELD_CASE(UInt32, unsignedIntValue)
+ FIELD_CASE(Fixed32, unsignedIntValue)
+ FIELD_CASE(UInt64, unsignedLongLongValue)
+ FIELD_CASE(Fixed64, unsignedLongLongValue)
+ FIELD_CASE2(Data)
+ FIELD_CASE2(String)
+ FIELD_CASE2(Group)
+ case GPBTypeMessage:
+ if (ExtensionIsWireFormat(description)) {
+ return GPBComputeMessageSetExtensionSize(description->fieldNumber,
+ object);
+ } else {
+ return GPBComputeMessageSize(description->fieldNumber, object);
+ }
+ }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static size_t ComputeSerializedSizeIncludingTagOfArray(
+ GPBExtensionDescription *description, NSArray *values) {
+ if (ExtensionIsPacked(description)) {
+ size_t size = 0;
+ size_t typeSize = TypeSize(description->type);
+ if (typeSize != 0) {
+ size = values.count * typeSize;
+ } else {
+ for (id value in values) {
+ size += ComputePBSerializedSizeNoTagOfObject(description->type, value);
+ }
+ }
+ return size + GPBComputeTagSize(description->fieldNumber) +
+ GPBComputeRawVarint32SizeForInteger(size);
+ } else {
+ size_t size = 0;
+ for (id value in values) {
+ size += ComputeSerializedSizeIncludingTagOfObject(description, value);
+ }
+ return size;
+ }
+}
+
+static void WriteObjectIncludingTagToCodedOutputStream(
+ id object, GPBExtensionDescription *description,
+ GPBCodedOutputStream *output) {
+#define FIELD_CASE(TYPE, ACCESSOR) \
+ case GPBType##TYPE: \
+ [output write##TYPE:description->fieldNumber \
+ value:[(NSNumber *)object ACCESSOR]]; \
+ return;
+#define FIELD_CASE2(TYPE) \
+ case GPBType##TYPE: \
+ [output write##TYPE:description->fieldNumber value:object]; \
+ return;
+ switch (description->type) {
+ FIELD_CASE(Bool, boolValue)
+ FIELD_CASE(Float, floatValue)
+ FIELD_CASE(Double, doubleValue)
+ FIELD_CASE(Int32, intValue)
+ FIELD_CASE(SFixed32, intValue)
+ FIELD_CASE(SInt32, intValue)
+ FIELD_CASE(Enum, intValue)
+ FIELD_CASE(Int64, longLongValue)
+ FIELD_CASE(SInt64, longLongValue)
+ FIELD_CASE(SFixed64, longLongValue)
+ FIELD_CASE(UInt32, unsignedIntValue)
+ FIELD_CASE(Fixed32, unsignedIntValue)
+ FIELD_CASE(UInt64, unsignedLongLongValue)
+ FIELD_CASE(Fixed64, unsignedLongLongValue)
+ FIELD_CASE2(Data)
+ FIELD_CASE2(String)
+ FIELD_CASE2(Group)
+ case GPBTypeMessage:
+ if (ExtensionIsWireFormat(description)) {
+ [output writeMessageSetExtension:description->fieldNumber value:object];
+ } else {
+ [output writeMessage:description->fieldNumber value:object];
+ }
+ return;
+ }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static void WriteObjectNoTagToCodedOutputStream(
+ id object, GPBExtensionDescription *description,
+ GPBCodedOutputStream *output) {
+#define FIELD_CASE(TYPE, ACCESSOR) \
+ case GPBType##TYPE: \
+ [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \
+ return;
+#define FIELD_CASE2(TYPE) \
+ case GPBType##TYPE: \
+ [output write##TYPE##NoTag:object]; \
+ return;
+ switch (description->type) {
+ FIELD_CASE(Bool, boolValue)
+ FIELD_CASE(Float, floatValue)
+ FIELD_CASE(Double, doubleValue)
+ FIELD_CASE(Int32, intValue)
+ FIELD_CASE(SFixed32, intValue)
+ FIELD_CASE(SInt32, intValue)
+ FIELD_CASE(Enum, intValue)
+ FIELD_CASE(Int64, longLongValue)
+ FIELD_CASE(SInt64, longLongValue)
+ FIELD_CASE(SFixed64, longLongValue)
+ FIELD_CASE(UInt32, unsignedIntValue)
+ FIELD_CASE(Fixed32, unsignedIntValue)
+ FIELD_CASE(UInt64, unsignedLongLongValue)
+ FIELD_CASE(Fixed64, unsignedLongLongValue)
+ FIELD_CASE2(Data)
+ FIELD_CASE2(String)
+ FIELD_CASE2(Message)
+ case GPBTypeGroup:
+ [output writeGroupNoTag:description->fieldNumber value:object];
+ return;
+ }
+#undef FIELD_CASE
+#undef FIELD_CASE2
+}
+
+static void WriteArrayIncludingTagsToCodedOutputStream(
+ NSArray *values, GPBExtensionDescription *description,
+ GPBCodedOutputStream *output) {
+ if (ExtensionIsPacked(description)) {
+ [output writeTag:description->fieldNumber
+ format:GPBWireFormatLengthDelimited];
+ size_t dataSize = 0;
+ size_t typeSize = TypeSize(description->type);
+ if (typeSize != 0) {
+ dataSize = values.count * typeSize;
+ } else {
+ for (id value in values) {
+ dataSize +=
+ ComputePBSerializedSizeNoTagOfObject(description->type, value);
+ }
+ }
+ [output writeRawVarintSizeTAs32:dataSize];
+ for (id value in values) {
+ WriteObjectNoTagToCodedOutputStream(value, description, output);
+ }
+ } else {
+ for (id value in values) {
+ WriteObjectIncludingTagToCodedOutputStream(value, description, output);
+ }
+ }
+}
+
+@implementation GPBExtensionField {
+ GPBExtensionDescription *description_;
+ GPBExtensionDescriptor *descriptor_;
+ GPBValue defaultValue_;
+}
+
+@synthesize containingType = containingType_;
+@synthesize descriptor = descriptor_;
+
+- (instancetype)init {
+ // Throw an exception if people attempt to not use the designated initializer.
+ self = [super init];
+ if (self != nil) {
+ [self doesNotRecognizeSelector:_cmd];
+ self = nil;
+ }
+ return self;
+}
+
+- (instancetype)initWithDescription:(GPBExtensionDescription *)description {
+ if ((self = [super init])) {
+ description_ = description;
+ if (description->extendedClass) {
+ Class containingClass = objc_lookUpClass(description->extendedClass);
+ NSAssert1(containingClass, @"Class %s not defined",
+ description->extendedClass);
+ containingType_ = [containingClass descriptor];
+ }
+#if DEBUG
+ const char *className = description->messageOrGroupClassName;
+ if (className) {
+ NSAssert1(objc_lookUpClass(className) != Nil, @"Class %s not defined",
+ className);
+ }
+#endif
+ descriptor_ = [[GPBExtensionDescriptor alloc]
+ initWithExtensionDescription:description];
+ GPBType type = description_->type;
+ if (type == GPBTypeData) {
+ // Data stored as a length prefixed c-string in descriptor records.
+ const uint8_t *bytes =
+ (const uint8_t *)description->defaultValue.valueData;
+ if (bytes) {
+ uint32_t length = *((uint32_t *)bytes);
+ // The length is stored in network byte order.
+ length = ntohl(length);
+ bytes += sizeof(length);
+ defaultValue_.valueData =
+ [[NSData alloc] initWithBytes:bytes length:length];
+ }
+ } else if (type == GPBTypeMessage || type == GPBTypeGroup) {
+ // The default is looked up in -defaultValue instead since extensions
+ // aren't
+ // common, we avoid the hit startup hit and it avoid initialization order
+ // issues.
+ } else {
+ defaultValue_ = description->defaultValue;
+ }
+ }
+ return self;
+}
+
+- (void)dealloc {
+ if ((description_->type == GPBTypeData) &&
+ !ExtensionIsRepeated(description_)) {
+ [defaultValue_.valueData release];
+ }
+ [descriptor_ release];
+ [super dealloc];
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"<%@ %p> FieldNumber:%d ContainingType:%@",
+ [self class], self, self.fieldNumber,
+ self.containingType];
+}
+
+- (id)copyWithZone:(NSZone *)__unused zone {
+ return [self retain];
+}
+
+#pragma mark Properties
+
+- (int32_t)fieldNumber {
+ return description_->fieldNumber;
+}
+
+- (GPBWireFormat)wireType {
+ return GPBWireFormatForType(description_->type,
+ ExtensionIsPacked(description_));
+}
+
+- (BOOL)isRepeated {
+ return ExtensionIsRepeated(description_);
+}
+
+- (id)defaultValue {
+ if (ExtensionIsRepeated(description_)) {
+ return nil;
+ }
+
+ switch (description_->type) {
+ case GPBTypeBool:
+ return @(defaultValue_.valueBool);
+ case GPBTypeFloat:
+ return @(defaultValue_.valueFloat);
+ case GPBTypeDouble:
+ return @(defaultValue_.valueDouble);
+ case GPBTypeInt32:
+ case GPBTypeSInt32:
+ case GPBTypeEnum:
+ case GPBTypeSFixed32:
+ return @(defaultValue_.valueInt32);
+ case GPBTypeInt64:
+ case GPBTypeSInt64:
+ case GPBTypeSFixed64:
+ return @(defaultValue_.valueInt64);
+ case GPBTypeUInt32:
+ case GPBTypeFixed32:
+ return @(defaultValue_.valueUInt32);
+ case GPBTypeUInt64:
+ case GPBTypeFixed64:
+ return @(defaultValue_.valueUInt64);
+ case GPBTypeData:
+ // Like message fields, the default is zero length data.
+ return (defaultValue_.valueData ? defaultValue_.valueData
+ : GPBEmptyNSData());
+ case GPBTypeString:
+ // Like message fields, the default is zero length string.
+ return (defaultValue_.valueString ? defaultValue_.valueString : @"");
+ case GPBTypeGroup:
+ case GPBTypeMessage:
+ NSAssert(0, @"Shouldn't get here");
+ return nil;
+ }
+}
+
+#pragma mark Internals
+
+- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+ message:(GPBMessage *)message {
+ GPBCodedInputStreamState *state = &input->state_;
+ if (ExtensionIsPacked(description_)) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ id value = [self newSingleValueFromCodedInputStream:input
+ extensionRegistry:extensionRegistry
+ existingValue:nil];
+ [message addExtension:self value:value];
+ [value release];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ id existingValue = nil;
+ BOOL isRepeated = ExtensionIsRepeated(description_);
+ if (!isRepeated && GPBTypeIsMessage(description_->type)) {
+ existingValue = [message getExistingExtension:self];
+ }
+ id value = [self newSingleValueFromCodedInputStream:input
+ extensionRegistry:extensionRegistry
+ existingValue:existingValue];
+ if (isRepeated) {
+ [message addExtension:self value:value];
+ } else {
+ [message setExtension:self value:value];
+ }
+ [value release];
+ }
+}
+
+- (void)writeValue:(id)value
+ includingTagToCodedOutputStream:(GPBCodedOutputStream *)output {
+ if (ExtensionIsRepeated(description_)) {
+ WriteArrayIncludingTagsToCodedOutputStream(value, description_, output);
+ } else {
+ WriteObjectIncludingTagToCodedOutputStream(value, description_, output);
+ }
+}
+
+- (size_t)computeSerializedSizeIncludingTag:(id)value {
+ if (ExtensionIsRepeated(description_)) {
+ return ComputeSerializedSizeIncludingTagOfArray(description_, value);
+ } else {
+ return ComputeSerializedSizeIncludingTagOfObject(description_, value);
+ }
+}
+
+// Note that this returns a retained value intentionally.
+- (id)newSingleValueFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+ existingValue:(GPBMessage *)existingValue {
+ GPBCodedInputStreamState *state = &input->state_;
+ switch (description_->type) {
+ case GPBTypeBool: return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)];
+ case GPBTypeFixed32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)];
+ case GPBTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)];
+ case GPBTypeFloat: return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)];
+ case GPBTypeFixed64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)];
+ case GPBTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)];
+ case GPBTypeDouble: return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)];
+ case GPBTypeInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)];
+ case GPBTypeInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)];
+ case GPBTypeSInt32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)];
+ case GPBTypeSInt64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)];
+ case GPBTypeUInt32: return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)];
+ case GPBTypeUInt64: return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)];
+ case GPBTypeData: return GPBCodedInputStreamReadRetainedData(state);
+ case GPBTypeString: return GPBCodedInputStreamReadRetainedString(state);
+ case GPBTypeEnum: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)];
+ case GPBTypeGroup:
+ case GPBTypeMessage: {
+ GPBMessage *message;
+ if (existingValue) {
+ message = [existingValue retain];
+ } else {
+ GPBDescriptor *decriptor = [descriptor_.msgClass descriptor];
+ message = [[decriptor.messageClass alloc] init];
+ }
+
+ if (description_->type == GPBTypeGroup) {
+ [input readGroup:description_->fieldNumber
+ message:message
+ extensionRegistry:extensionRegistry];
+ } else {
+ // description_->type == GPBTypeMessage
+ if (ExtensionIsWireFormat(description_)) {
+ // For MessageSet fields the message length will have already been
+ // read.
+ [message mergeFromCodedInputStream:input
+ extensionRegistry:extensionRegistry];
+ } else {
+ [input readMessage:message extensionRegistry:extensionRegistry];
+ }
+ }
+
+ return message;
+ }
+ }
+
+ return nil;
+}
+
+- (NSComparisonResult)compareByFieldNumber:(GPBExtensionField *)other {
+ int32_t selfNumber = description_->fieldNumber;
+ int32_t otherNumber = other->description_->fieldNumber;
+ if (selfNumber < otherNumber) {
+ return NSOrderedAscending;
+ } else if (selfNumber == otherNumber) {
+ return NSOrderedSame;
+ } else {
+ return NSOrderedDescending;
+ }
+}
+
+@end
diff --git a/objectivec/GPBExtensionField_PackagePrivate.h b/objectivec/GPBExtensionField_PackagePrivate.h
new file mode 100644
index 00000000..6256b9a7
--- /dev/null
+++ b/objectivec/GPBExtensionField_PackagePrivate.h
@@ -0,0 +1,51 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBExtensionField.h"
+
+struct GPBExtensionDescription;
+
+@interface GPBExtensionField ()
+
+- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+ message:(GPBMessage *)message;
+
+- (instancetype)initWithDescription:(struct GPBExtensionDescription *)description;
+
+- (size_t)computeSerializedSizeIncludingTag:(id)value;
+- (void)writeValue:(id)value
+ includingTagToCodedOutputStream:(GPBCodedOutputStream *)output;
+
+- (NSComparisonResult)compareByFieldNumber:(GPBExtensionField *)other;
+
+@end
diff --git a/objectivec/GPBExtensionRegistry.h b/objectivec/GPBExtensionRegistry.h
new file mode 100644
index 00000000..ce1f8fab
--- /dev/null
+++ b/objectivec/GPBExtensionRegistry.h
@@ -0,0 +1,46 @@
+// 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 <Foundation/Foundation.h>
+
+@class GPBDescriptor;
+@class GPBExtensionField;
+
+// A table of known extensions, searchable by name or field number. When
+// parsing a protocol message that might have extensions, you must provide an
+// ExtensionRegistry in which you have registered any extensions that you want
+// to be able to parse. Otherwise, those extensions will just be treated like
+// unknown fields.
+@interface GPBExtensionRegistry : NSObject
+
+- (GPBExtensionField *)getExtension:(GPBDescriptor *)containingType
+ fieldNumber:(NSInteger)fieldNumber;
+
+@end
diff --git a/objectivec/GPBExtensionRegistry.m b/objectivec/GPBExtensionRegistry.m
new file mode 100644
index 00000000..a191dace
--- /dev/null
+++ b/objectivec/GPBExtensionRegistry.m
@@ -0,0 +1,98 @@
+// 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 "GPBExtensionRegistry_PackagePrivate.h"
+
+#import "GPBBootstrap.h"
+#import "GPBDescriptor.h"
+#import "GPBExtensionField.h"
+
+@implementation GPBExtensionRegistry {
+ // TODO(dmaclach): Reimplement with CFDictionaries that don't use
+ // objects as keys.
+ NSMutableDictionary *mutableClassMap_;
+}
+
+- (instancetype)init {
+ if ((self = [super init])) {
+ mutableClassMap_ = [[NSMutableDictionary alloc] init];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [mutableClassMap_ release];
+ [super dealloc];
+}
+
+- (NSMutableDictionary *)extensionMapForContainingType:
+ (GPBDescriptor *)containingType {
+ NSMutableDictionary *extensionMap =
+ [mutableClassMap_ objectForKey:containingType];
+ if (extensionMap == nil) {
+ extensionMap = [NSMutableDictionary dictionary];
+ [mutableClassMap_ setObject:extensionMap forKey:containingType];
+ }
+ return extensionMap;
+}
+
+- (void)addExtension:(GPBExtensionField *)extension {
+ if (extension == nil) {
+ return;
+ }
+
+ GPBDescriptor *containingType = [extension containingType];
+ NSMutableDictionary *extensionMap =
+ [self extensionMapForContainingType:containingType];
+ [extensionMap setObject:extension forKey:@([extension fieldNumber])];
+}
+
+- (GPBExtensionField *)getExtension:(GPBDescriptor *)containingType
+ fieldNumber:(NSInteger)fieldNumber {
+ NSDictionary *extensionMap = [mutableClassMap_ objectForKey:containingType];
+ return [extensionMap objectForKey:@(fieldNumber)];
+}
+
+- (void)addExtensions:(GPBExtensionRegistry *)registry {
+ if (registry == nil) {
+ // In the case where there are no extensions just ignore.
+ return;
+ }
+ NSMutableDictionary *otherClassMap = registry->mutableClassMap_;
+ for (GPBDescriptor *containingType in otherClassMap) {
+ NSMutableDictionary *extensionMap =
+ [self extensionMapForContainingType:containingType];
+ NSMutableDictionary *otherExtensionMap =
+ [registry extensionMapForContainingType:containingType];
+ [extensionMap addEntriesFromDictionary:otherExtensionMap];
+ }
+}
+
+@end
diff --git a/objectivec/GPBExtensionRegistry_PackagePrivate.h b/objectivec/GPBExtensionRegistry_PackagePrivate.h
new file mode 100644
index 00000000..968cb1fd
--- /dev/null
+++ b/objectivec/GPBExtensionRegistry_PackagePrivate.h
@@ -0,0 +1,40 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBExtensionRegistry.h"
+
+@interface GPBExtensionRegistry ()
+
+- (void)addExtension:(GPBExtensionField *)extension;
+- (void)addExtensions:(GPBExtensionRegistry *)registry;
+
+@end
diff --git a/objectivec/GPBField.h b/objectivec/GPBField.h
new file mode 100644
index 00000000..041a242f
--- /dev/null
+++ b/objectivec/GPBField.h
@@ -0,0 +1,56 @@
+// 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 <Foundation/Foundation.h>
+
+@class GPBCodedOutputStream;
+@class GPBUInt32Array;
+@class GPBUInt64Array;
+@class GPBUnknownFieldSet;
+
+@interface GPBField : NSObject<NSCopying>
+
+@property(nonatomic, readonly, assign) int32_t number;
+
+// Only one of these will be set.
+@property(nonatomic, readonly, strong) GPBUInt64Array *varintList;
+@property(nonatomic, readonly, strong) GPBUInt32Array *fixed32List;
+@property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List;
+@property(nonatomic, readonly, strong) NSArray *lengthDelimitedList;
+@property(nonatomic, readonly, strong) NSArray *groupList;
+
+// Only one of these should be used per Field.
+- (void)addVarint:(uint64_t)value;
+- (void)addFixed32:(uint32_t)value;
+- (void)addFixed64:(uint64_t)value;
+- (void)addLengthDelimited:(NSData *)value;
+- (void)addGroup:(GPBUnknownFieldSet *)value;
+
+@end
diff --git a/objectivec/GPBField.m b/objectivec/GPBField.m
new file mode 100644
index 00000000..c390ae9e
--- /dev/null
+++ b/objectivec/GPBField.m
@@ -0,0 +1,328 @@
+// 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 "GPBField_PackagePrivate.h"
+
+#import "GPBArray.h"
+#import "GPBCodedOutputStream.h"
+
+@interface GPBField () {
+ @protected
+ int32_t number_;
+ GPBUInt64Array *mutableVarintList_;
+ GPBUInt32Array *mutableFixed32List_;
+ GPBUInt64Array *mutableFixed64List_;
+ NSMutableArray *mutableLengthDelimitedList_;
+ NSMutableArray *mutableGroupList_;
+}
+@end
+
+@implementation GPBField
+
+@synthesize number = number_;
+@synthesize varintList = mutableVarintList_;
+@synthesize fixed32List = mutableFixed32List_;
+@synthesize fixed64List = mutableFixed64List_;
+@synthesize lengthDelimitedList = mutableLengthDelimitedList_;
+@synthesize groupList = mutableGroupList_;
+
+- (instancetype)initWithNumber:(int32_t)number {
+ if ((self = [super init])) {
+ number_ = number;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [mutableVarintList_ release];
+ [mutableFixed32List_ release];
+ [mutableFixed64List_ release];
+ [mutableLengthDelimitedList_ release];
+ [mutableGroupList_ release];
+
+ [super dealloc];
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+ GPBField *result = [[GPBField allocWithZone:zone] initWithNumber:number_];
+ result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone];
+ result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone];
+ result->mutableLengthDelimitedList_ =
+ [mutableLengthDelimitedList_ copyWithZone:zone];
+ result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone];
+ if (mutableGroupList_.count) {
+ result->mutableGroupList_ = [[NSMutableArray allocWithZone:zone]
+ initWithCapacity:mutableGroupList_.count];
+ for (GPBUnknownFieldSet *group in mutableGroupList_) {
+ GPBUnknownFieldSet *copied = [group copyWithZone:zone];
+ [result->mutableGroupList_ addObject:copied];
+ [copied release];
+ }
+ }
+ return result;
+}
+
+- (BOOL)isEqual:(id)object {
+ if (self == object) return YES;
+ if (![object isKindOfClass:[GPBField class]]) return NO;
+ GPBField *field = (GPBField *)object;
+ BOOL equalVarint =
+ (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) ||
+ [mutableVarintList_ isEqual:field->mutableVarintList_];
+ if (!equalVarint) return NO;
+ BOOL equalFixed32 = (mutableFixed32List_.count == 0 &&
+ field->mutableFixed32List_.count == 0) ||
+ [mutableFixed32List_ isEqual:field->mutableFixed32List_];
+ if (!equalFixed32) return NO;
+ BOOL equalFixed64 = (mutableFixed64List_.count == 0 &&
+ field->mutableFixed64List_.count == 0) ||
+ [mutableFixed64List_ isEqual:field->mutableFixed64List_];
+ if (!equalFixed64) return NO;
+ BOOL equalLDList =
+ (mutableLengthDelimitedList_.count == 0 &&
+ field->mutableLengthDelimitedList_.count == 0) ||
+ [mutableLengthDelimitedList_ isEqual:field->mutableLengthDelimitedList_];
+ if (!equalLDList) return NO;
+ BOOL equalGroupList =
+ (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) ||
+ [mutableGroupList_ isEqual:field->mutableGroupList_];
+ if (!equalGroupList) return NO;
+ return YES;
+}
+
+- (NSUInteger)hash {
+ // Just mix the hashes of the possible sub arrays.
+ const int prime = 31;
+ NSUInteger result = prime + [mutableVarintList_ hash];
+ result = prime * result + [mutableFixed32List_ hash];
+ result = prime * result + [mutableFixed64List_ hash];
+ result = prime * result + [mutableLengthDelimitedList_ hash];
+ result = prime * result + [mutableGroupList_ hash];
+ return result;
+}
+
+- (void)writeToOutput:(GPBCodedOutputStream *)output {
+ NSUInteger count = mutableVarintList_.count;
+ if (count > 0) {
+ [output writeUInt64s:number_ values:mutableVarintList_ tag:0];
+ }
+ count = mutableFixed32List_.count;
+ if (count > 0) {
+ [output writeFixed32s:number_ values:mutableFixed32List_ tag:0];
+ }
+ count = mutableFixed64List_.count;
+ if (count > 0) {
+ [output writeFixed64s:number_ values:mutableFixed64List_ tag:0];
+ }
+ count = mutableLengthDelimitedList_.count;
+ if (count > 0) {
+ [output writeDatas:number_ values:mutableLengthDelimitedList_];
+ }
+ count = mutableGroupList_.count;
+ if (count > 0) {
+ [output writeUnknownGroups:number_ values:mutableGroupList_];
+ }
+}
+
+- (size_t)serializedSize {
+ __block size_t result = 0;
+ int32_t number = number_;
+ [mutableVarintList_
+ enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ result += GPBComputeUInt64Size(number, value);
+ }];
+
+ [mutableFixed32List_
+ enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ result += GPBComputeFixed32Size(number, value);
+ }];
+
+ [mutableFixed64List_
+ enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ result += GPBComputeFixed64Size(number, value);
+ }];
+
+ for (NSData *data in mutableLengthDelimitedList_) {
+ result += GPBComputeDataSize(number, data);
+ }
+
+ for (GPBUnknownFieldSet *set in mutableGroupList_) {
+ result += GPBComputeUnknownGroupSize(number, set);
+ }
+
+ return result;
+}
+
+- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output {
+ for (NSData *data in mutableLengthDelimitedList_) {
+ [output writeRawMessageSetExtension:number_ value:data];
+ }
+}
+
+- (size_t)serializedSizeAsMessageSetExtension {
+ size_t result = 0;
+ for (NSData *data in mutableLengthDelimitedList_) {
+ result += GPBComputeRawMessageSetExtensionSize(number_, data);
+ }
+ return result;
+}
+
+- (NSString *)description {
+ NSMutableString *description = [NSMutableString
+ stringWithFormat:@"<%@ %p>: Field: %d {\n", [self class], self, number_];
+ [mutableVarintList_
+ enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [description appendFormat:@"\t%llu\n", value];
+ }];
+
+ [mutableFixed32List_
+ enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [description appendFormat:@"\t%u\n", value];
+ }];
+
+ [mutableFixed64List_
+ enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+#pragma unused(idx, stop)
+ [description appendFormat:@"\t%llu\n", value];
+ }];
+
+ for (NSData *data in mutableLengthDelimitedList_) {
+ [description appendFormat:@"\t%@\n", data];
+ }
+
+ for (GPBUnknownFieldSet *set in mutableGroupList_) {
+ [description appendFormat:@"\t%@\n", set];
+ }
+ [description appendString:@"}"];
+ return description;
+}
+
+- (void)mergeFromField:(GPBField *)other {
+ GPBUInt64Array *otherVarintList = other.varintList;
+ if (otherVarintList.count > 0) {
+ if (mutableVarintList_ == nil) {
+ mutableVarintList_ = [otherVarintList copy];
+ } else {
+ [mutableVarintList_ addValuesFromArray:otherVarintList];
+ }
+ }
+
+ GPBUInt32Array *otherFixed32List = other.fixed32List;
+ if (otherFixed32List.count > 0) {
+ if (mutableFixed32List_ == nil) {
+ mutableFixed32List_ = [otherFixed32List copy];
+ } else {
+ [mutableFixed32List_ addValuesFromArray:otherFixed32List];
+ }
+ }
+
+ GPBUInt64Array *otherFixed64List = other.fixed64List;
+ if (otherFixed64List.count > 0) {
+ if (mutableFixed64List_ == nil) {
+ mutableFixed64List_ = [otherFixed64List copy];
+ } else {
+ [mutableFixed64List_ addValuesFromArray:otherFixed64List];
+ }
+ }
+
+ NSArray *otherLengthDelimitedList = other.lengthDelimitedList;
+ if (otherLengthDelimitedList.count > 0) {
+ if (mutableLengthDelimitedList_ == nil) {
+ mutableLengthDelimitedList_ = [otherLengthDelimitedList mutableCopy];
+ } else {
+ [mutableLengthDelimitedList_
+ addObjectsFromArray:otherLengthDelimitedList];
+ }
+ }
+
+ NSArray *otherGroupList = other.groupList;
+ if (otherGroupList.count > 0) {
+ if (mutableGroupList_ == nil) {
+ mutableGroupList_ =
+ [[NSMutableArray alloc] initWithCapacity:otherGroupList.count];
+ }
+ // Make our own mutable copies.
+ for (GPBUnknownFieldSet *group in otherGroupList) {
+ GPBUnknownFieldSet *copied = [group copy];
+ [mutableGroupList_ addObject:copied];
+ [copied release];
+ }
+ }
+}
+
+- (void)addVarint:(uint64_t)value {
+ if (mutableVarintList_ == nil) {
+ mutableVarintList_ = [[GPBUInt64Array alloc] initWithValues:&value count:1];
+ } else {
+ [mutableVarintList_ addValue:value];
+ }
+}
+
+- (void)addFixed32:(uint32_t)value {
+ if (mutableFixed32List_ == nil) {
+ mutableFixed32List_ =
+ [[GPBUInt32Array alloc] initWithValues:&value count:1];
+ } else {
+ [mutableFixed32List_ addValue:value];
+ }
+}
+
+- (void)addFixed64:(uint64_t)value {
+ if (mutableFixed64List_ == nil) {
+ mutableFixed64List_ =
+ [[GPBUInt64Array alloc] initWithValues:&value count:1];
+ } else {
+ [mutableFixed64List_ addValue:value];
+ }
+}
+
+- (void)addLengthDelimited:(NSData *)value {
+ if (mutableLengthDelimitedList_ == nil) {
+ mutableLengthDelimitedList_ =
+ [[NSMutableArray alloc] initWithObjects:&value count:1];
+ } else {
+ [mutableLengthDelimitedList_ addObject:value];
+ }
+}
+
+- (void)addGroup:(GPBUnknownFieldSet *)value {
+ if (mutableGroupList_ == nil) {
+ mutableGroupList_ = [[NSMutableArray alloc] initWithObjects:&value count:1];
+ } else {
+ [mutableGroupList_ addObject:value];
+ }
+}
+
+@end
diff --git a/objectivec/GPBField_PackagePrivate.h b/objectivec/GPBField_PackagePrivate.h
new file mode 100644
index 00000000..73c1fa80
--- /dev/null
+++ b/objectivec/GPBField_PackagePrivate.h
@@ -0,0 +1,49 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBField.h"
+
+@class GPBCodedOutputStream;
+
+@interface GPBField ()
+
+- (instancetype)initWithNumber:(int32_t)number;
+
+- (void)writeToOutput:(GPBCodedOutputStream *)output;
+- (size_t)serializedSize;
+
+- (void)writeAsMessageSetExtensionToOutput:(GPBCodedOutputStream *)output;
+- (size_t)serializedSizeAsMessageSetExtension;
+
+- (void)mergeFromField:(GPBField *)other;
+
+@end
diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h
new file mode 100644
index 00000000..2483f5d3
--- /dev/null
+++ b/objectivec/GPBMessage.h
@@ -0,0 +1,151 @@
+// 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 "GPBRootObject.h"
+
+@class GPBDescriptor;
+@class GPBCodedInputStream;
+@class GPBCodedOutputStream;
+@class GPBExtensionField;
+@class GPBFieldDescriptor;
+@class GPBUnknownFieldSet;
+
+// In DEBUG ONLY, an NSException is thrown when a parsed message doesn't
+// contain required fields. This key allows you to retrieve the parsed message
+// from the exception's |userInfo| dictionary.
+#ifdef DEBUG
+extern NSString *const GPBExceptionMessageKey;
+#endif // DEBUG
+
+// NOTE:
+// If you add a instance method/property to this class that may conflict with
+// methods declared in protos, you need to update objective_helpers.cc.
+// The main cases are methods that take no arguments, or setFoo:/hasFoo: type
+// methods.
+@interface GPBMessage : GPBRootObject<NSCoding, NSCopying>
+
+@property(nonatomic, readonly) GPBUnknownFieldSet *unknownFields;
+
+// Are all required fields in the message and all embedded messages set.
+@property(nonatomic, readonly, getter=isInitialized) BOOL initialized;
+
+// Returns an autoreleased instance.
++ (instancetype)message;
+
+// Create a message based on a variety of inputs.
+// In DEBUG ONLY
+// @throws NSInternalInconsistencyException The message is missing one or more
+// required fields (i.e. -[isInitialized] returns false). Use
+// GGPBExceptionMessageKey to retrieve the message from |userInfo|.
++ (instancetype)parseFromData:(NSData *)data;
++ (instancetype)parseFromData:(NSData *)data
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry;
++ (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:
+ (GPBExtensionRegistry *)extensionRegistry;
+
+// Create a message based on delimited input.
++ (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:
+ (GPBExtensionRegistry *)extensionRegistry;
+
+- (instancetype)initWithData:(NSData *)data;
+- (instancetype)initWithData:(NSData *)data
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry;
+- (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:
+ (GPBExtensionRegistry *)extensionRegistry;
+
+// Serializes the message and writes it to output.
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output;
+- (void)writeToOutputStream:(NSOutputStream *)output;
+
+// Serializes the message and writes it to output, but writes the size of the
+// message as a variant before writing the message.
+- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output;
+- (void)writeDelimitedToOutputStream:(NSOutputStream *)output;
+
+// Serializes the message to an NSData. Note that this value is not cached, so
+// if you are using it repeatedly, cache it yourself.
+// In DEBUG ONLY:
+// @throws NSInternalInconsistencyException The message is missing one or more
+// required fields (i.e. -[isInitialized] returns false). Use
+// GPBExceptionMessageKey to retrieve the message from |userInfo|.
+- (NSData *)data;
+
+// Same as -[data], except a delimiter is added to the start of the data
+// indicating the size of the message data that follows.
+- (NSData *)delimitedData;
+
+// Returns the size of the object if it were serialized.
+// This is not a cached value. If you are following a pattern like this:
+// size_t size = [aMsg serializedSize];
+// NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)];
+// [foo writeSize:size];
+// [foo appendData:[aMsg data]];
+// you would be better doing:
+// NSData *data = [aMsg data];
+// NSUInteger size = [aMsg length];
+// NSMutableData *foo = [NSMutableData dataWithCapacity:size + sizeof(size)];
+// [foo writeSize:size];
+// [foo appendData:data];
+- (size_t)serializedSize;
+
+// Return the descriptor for the message
++ (GPBDescriptor *)descriptor;
+- (GPBDescriptor *)descriptor;
+
+// Extensions use boxed values (NSNumbers) for PODs, NSMutableArrays for
+// repeated. If the extension is a Message, just like fields, one will be
+// auto created for you and returned.
+- (BOOL)hasExtension:(GPBExtensionField *)extension;
+- (id)getExtension:(GPBExtensionField *)extension;
+- (void)setExtension:(GPBExtensionField *)extension value:(id)value;
+- (void)addExtension:(GPBExtensionField *)extension value:(id)value;
+- (void)setExtension:(GPBExtensionField *)extension
+ index:(NSUInteger)index
+ value:(id)value;
+- (void)clearExtension:(GPBExtensionField *)extension;
+
+- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields;
+
+// Resets all fields to their default values.
+- (void)clear;
+
+// Parses a message of this type from the input and merges it with this
+// message.
+- (void)mergeFromData:(NSData *)data
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry;
+
+// Merges the fields from another message (of the same type) into this
+// message.
+- (void)mergeFrom:(GPBMessage *)other;
+
+@end
diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m
new file mode 100644
index 00000000..63ffc3bc
--- /dev/null
+++ b/objectivec/GPBMessage.m
@@ -0,0 +1,4735 @@
+// 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 "GPBMessage_PackagePrivate.h"
+
+#import <objc/runtime.h>
+#import <objc/message.h>
+
+#import "GPBArray_PackagePrivate.h"
+#import "GPBCodedInputStream_PackagePrivate.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBDictionary_PackagePrivate.h"
+#import "GPBExtensionField_PackagePrivate.h"
+#import "GPBExtensionRegistry_PackagePrivate.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+#ifdef DEBUG
+NSString *const GPBExceptionMessageKey =
+ GPBNSStringifySymbol(GPBExceptionMessage);
+#endif // DEBUG
+
+//
+// PLEASE REMEMBER:
+//
+// This is the base class for *all* messages generated, so any selector defined,
+// *public* or *private* could end up colliding with a proto message field. So
+// avoid using selectors that could match a property, use C functions to hide
+// them, etc.
+//
+
+@interface GPBMessage () {
+ @package
+ GPBUnknownFieldSet *unknownFields_;
+ NSMutableDictionary *extensionMap_;
+ NSMutableDictionary *autocreatedExtensionMap_;
+
+ // If the object was autocreated, we remember the creator so that if we get
+ // mutated, we can inform the creator to make our field visible.
+ GPBMessage *autocreator_;
+ GPBFieldDescriptor *autocreatorField_;
+ GPBExtensionField *autocreatorExtension_;
+}
+@end
+
+static id CreateArrayForField(GPBFieldDescriptor *field,
+ GPBMessage *autocreator)
+ __attribute__((ns_returns_retained));
+static id GetOrCreateArrayIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ GPBFileSyntax syntax);
+static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
+static id GetOrCreateMapIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ GPBFileSyntax syntax);
+static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
+ NSZone *zone)
+ __attribute__((ns_returns_retained));
+
+static void CheckExtension(GPBMessage *self, GPBExtensionField *extension) {
+ if ([[self class] descriptor] != [extension containingType]) {
+ [NSException
+ raise:NSInvalidArgumentException
+ format:@"Extension %@ used on wrong class (%@ instead of %@)",
+ extension.descriptor.singletonName,
+ [[self class] descriptor].name, [extension containingType].name];
+ }
+}
+
+static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
+ NSZone *zone) {
+ if (extensionMap.count == 0) {
+ return nil;
+ }
+ NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone]
+ initWithCapacity:extensionMap.count];
+
+ for (GPBExtensionField *field in extensionMap) {
+ id value = [extensionMap objectForKey:field];
+ GPBExtensionDescriptor *fieldDescriptor = field.descriptor;
+ BOOL isMessageExtension = GPBExtensionIsMessage(fieldDescriptor);
+
+ if ([field isRepeated]) {
+ if (isMessageExtension) {
+ NSMutableArray *list =
+ [[NSMutableArray alloc] initWithCapacity:[value count]];
+ for (GPBMessage *listValue in value) {
+ GPBMessage *copiedValue = [listValue copyWithZone:zone];
+ [list addObject:copiedValue];
+ [copiedValue release];
+ }
+ [result setObject:list forKey:field];
+ [list release];
+ } else {
+ NSMutableArray *copiedValue = [value mutableCopyWithZone:zone];
+ [result setObject:copiedValue forKey:field];
+ [copiedValue release];
+ }
+ } else {
+ if (isMessageExtension) {
+ GPBMessage *copiedValue = [value copyWithZone:zone];
+ [result setObject:copiedValue forKey:field];
+ [copiedValue release];
+ } else {
+ [result setObject:value forKey:field];
+ }
+ }
+ }
+
+ return result;
+}
+
+static id CreateArrayForField(GPBFieldDescriptor *field,
+ GPBMessage *autocreator) {
+ id result;
+ GPBType fieldDataType = GPBGetFieldType(field);
+ switch (fieldDataType) {
+ case GPBTypeBool:
+ result = [[GPBBoolArray alloc] init];
+ break;
+ case GPBTypeFixed32:
+ case GPBTypeUInt32:
+ result = [[GPBUInt32Array alloc] init];
+ break;
+ case GPBTypeInt32:
+ case GPBTypeSFixed32:
+ case GPBTypeSInt32:
+ result = [[GPBInt32Array alloc] init];
+ break;
+ case GPBTypeFixed64:
+ case GPBTypeUInt64:
+ result = [[GPBUInt64Array alloc] init];
+ break;
+ case GPBTypeInt64:
+ case GPBTypeSFixed64:
+ case GPBTypeSInt64:
+ result = [[GPBInt64Array alloc] init];
+ break;
+ case GPBTypeFloat:
+ result = [[GPBFloatArray alloc] init];
+ break;
+ case GPBTypeDouble:
+ result = [[GPBDoubleArray alloc] init];
+ break;
+
+ case GPBTypeEnum:
+ result = [[GPBEnumArray alloc]
+ initWithValidationFunction:field.enumDescriptor.enumVerifier];
+ break;
+
+ case GPBTypeData:
+ case GPBTypeGroup:
+ case GPBTypeMessage:
+ case GPBTypeString:
+ if (autocreator) {
+ result = [[GPBAutocreatedArray alloc] init];
+ } else {
+ result = [[NSMutableArray alloc] init];
+ }
+ break;
+ }
+
+ if (autocreator) {
+ if (GPBTypeIsObject(fieldDataType)) {
+ GPBAutocreatedArray *autoArray = result;
+ autoArray->_autocreator = autocreator;
+ } else {
+ GPBInt32Array *gpbArray = result;
+ gpbArray->_autocreator = autocreator;
+ }
+ }
+
+ return result;
+}
+
+
+#if !defined(__clang_analyzer__)
+// These functions are blocked from the analyzer because the analyzer sees the
+// GPBSetRetainedObjectIvarWithFieldInternal() call as consuming the array/map,
+// so use of the array/map after the call returns is flagged as a use after
+// free.
+// But GPBSetRetainedObjectIvarWithFieldInternal() is "consuming" the retain
+// count be holding onto the object (it is transfering it), the object is
+// still valid after returning from the call. The other way to avoid this
+// would be to add a -retain/-autorelease, but that would force every
+// repeated/map field parsed into the autorelease pool which is both a memory
+// and performance hit.
+
+static id GetOrCreateArrayIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ GPBFileSyntax syntax) {
+ id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (!array) {
+ // No lock needed, this is called from places expecting to mutate
+ // so no threading protection is needed.
+ array = CreateArrayForField(field, nil);
+ GPBSetRetainedObjectIvarWithFieldInternal(self, field, array, syntax);
+ }
+ return array;
+}
+
+// This is like GPBGetObjectIvarWithField(), but for arrays, it should
+// only be used to wire the method into the class.
+static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
+ id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (!array) {
+ // Check again after getting the lock.
+ OSSpinLockLock(&self->readOnlyMutex_);
+ array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (!array) {
+ array = CreateArrayForField(field, self);
+ GPBSetAutocreatedRetainedObjectIvarWithField(self, field, array);
+ }
+ OSSpinLockUnlock(&self->readOnlyMutex_);
+ }
+ return array;
+}
+
+static id GetOrCreateMapIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ GPBFileSyntax syntax) {
+ id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (!dict) {
+ GPBType keyType = field.mapKeyType;
+ GPBType valueType = GPBGetFieldType(field);
+ switch (keyType) {
+ case GPBTypeBool:
+ switch (valueType) {
+ case GPBTypeBool:
+ dict = [[GPBBoolBoolDictionary alloc] init];
+ break;
+ case GPBTypeFixed32:
+ case GPBTypeUInt32:
+ dict = [[GPBBoolUInt32Dictionary alloc] init];
+ break;
+ case GPBTypeInt32:
+ case GPBTypeSFixed32:
+ case GPBTypeSInt32:
+ dict = [[GPBBoolInt32Dictionary alloc] init];
+ break;
+ case GPBTypeFixed64:
+ case GPBTypeUInt64:
+ dict = [[GPBBoolUInt64Dictionary alloc] init];
+ break;
+ case GPBTypeInt64:
+ case GPBTypeSFixed64:
+ case GPBTypeSInt64:
+ dict = [[GPBBoolInt64Dictionary alloc] init];
+ break;
+ case GPBTypeFloat:
+ dict = [[GPBBoolFloatDictionary alloc] init];
+ break;
+ case GPBTypeDouble:
+ dict = [[GPBBoolDoubleDictionary alloc] init];
+ break;
+ case GPBTypeEnum:
+ dict = [[GPBBoolEnumDictionary alloc]
+ initWithValidationFunction:field.enumDescriptor.enumVerifier];
+ break;
+ case GPBTypeData:
+ case GPBTypeMessage:
+ case GPBTypeString:
+ dict = [[GPBBoolObjectDictionary alloc] init];
+ break;
+ case GPBTypeGroup:
+ NSCAssert(NO, @"shouldn't happen");
+ return nil;
+ }
+ break;
+ case GPBTypeFixed32:
+ case GPBTypeUInt32:
+ switch (valueType) {
+ case GPBTypeBool:
+ dict = [[GPBUInt32BoolDictionary alloc] init];
+ break;
+ case GPBTypeFixed32:
+ case GPBTypeUInt32:
+ dict = [[GPBUInt32UInt32Dictionary alloc] init];
+ break;
+ case GPBTypeInt32:
+ case GPBTypeSFixed32:
+ case GPBTypeSInt32:
+ dict = [[GPBUInt32Int32Dictionary alloc] init];
+ break;
+ case GPBTypeFixed64:
+ case GPBTypeUInt64:
+ dict = [[GPBUInt32UInt64Dictionary alloc] init];
+ break;
+ case GPBTypeInt64:
+ case GPBTypeSFixed64:
+ case GPBTypeSInt64:
+ dict = [[GPBUInt32Int64Dictionary alloc] init];
+ break;
+ case GPBTypeFloat:
+ dict = [[GPBUInt32FloatDictionary alloc] init];
+ break;
+ case GPBTypeDouble:
+ dict = [[GPBUInt32DoubleDictionary alloc] init];
+ break;
+ case GPBTypeEnum:
+ dict = [[GPBUInt32EnumDictionary alloc]
+ initWithValidationFunction:field.enumDescriptor.enumVerifier];
+ break;
+ case GPBTypeData:
+ case GPBTypeMessage:
+ case GPBTypeString:
+ dict = [[GPBUInt32ObjectDictionary alloc] init];
+ break;
+ case GPBTypeGroup:
+ NSCAssert(NO, @"shouldn't happen");
+ return nil;
+ }
+ break;
+ case GPBTypeInt32:
+ case GPBTypeSFixed32:
+ case GPBTypeSInt32:
+ switch (valueType) {
+ case GPBTypeBool:
+ dict = [[GPBInt32BoolDictionary alloc] init];
+ break;
+ case GPBTypeFixed32:
+ case GPBTypeUInt32:
+ dict = [[GPBInt32UInt32Dictionary alloc] init];
+ break;
+ case GPBTypeInt32:
+ case GPBTypeSFixed32:
+ case GPBTypeSInt32:
+ dict = [[GPBInt32Int32Dictionary alloc] init];
+ break;
+ case GPBTypeFixed64:
+ case GPBTypeUInt64:
+ dict = [[GPBInt32UInt64Dictionary alloc] init];
+ break;
+ case GPBTypeInt64:
+ case GPBTypeSFixed64:
+ case GPBTypeSInt64:
+ dict = [[GPBInt32Int64Dictionary alloc] init];
+ break;
+ case GPBTypeFloat:
+ dict = [[GPBInt32FloatDictionary alloc] init];
+ break;
+ case GPBTypeDouble:
+ dict = [[GPBInt32DoubleDictionary alloc] init];
+ break;
+ case GPBTypeEnum:
+ dict = [[GPBInt32EnumDictionary alloc]
+ initWithValidationFunction:field.enumDescriptor.enumVerifier];
+ break;
+ case GPBTypeData:
+ case GPBTypeMessage:
+ case GPBTypeString:
+ dict = [[GPBInt32ObjectDictionary alloc] init];
+ break;
+ case GPBTypeGroup:
+ NSCAssert(NO, @"shouldn't happen");
+ return nil;
+ }
+ break;
+ case GPBTypeFixed64:
+ case GPBTypeUInt64:
+ switch (valueType) {
+ case GPBTypeBool:
+ dict = [[GPBUInt64BoolDictionary alloc] init];
+ break;
+ case GPBTypeFixed32:
+ case GPBTypeUInt32:
+ dict = [[GPBUInt64UInt32Dictionary alloc] init];
+ break;
+ case GPBTypeInt32:
+ case GPBTypeSFixed32:
+ case GPBTypeSInt32:
+ dict = [[GPBUInt64Int32Dictionary alloc] init];
+ break;
+ case GPBTypeFixed64:
+ case GPBTypeUInt64:
+ dict = [[GPBUInt64UInt64Dictionary alloc] init];
+ break;
+ case GPBTypeInt64:
+ case GPBTypeSFixed64:
+ case GPBTypeSInt64:
+ dict = [[GPBUInt64Int64Dictionary alloc] init];
+ break;
+ case GPBTypeFloat:
+ dict = [[GPBUInt64FloatDictionary alloc] init];
+ break;
+ case GPBTypeDouble:
+ dict = [[GPBUInt64DoubleDictionary alloc] init];
+ break;
+ case GPBTypeEnum:
+ dict = [[GPBUInt64EnumDictionary alloc]
+ initWithValidationFunction:field.enumDescriptor.enumVerifier];
+ break;
+ case GPBTypeData:
+ case GPBTypeMessage:
+ case GPBTypeString:
+ dict = [[GPBUInt64ObjectDictionary alloc] init];
+ break;
+ case GPBTypeGroup:
+ NSCAssert(NO, @"shouldn't happen");
+ return nil;
+ }
+ break;
+ case GPBTypeInt64:
+ case GPBTypeSFixed64:
+ case GPBTypeSInt64:
+ switch (valueType) {
+ case GPBTypeBool:
+ dict = [[GPBInt64BoolDictionary alloc] init];
+ break;
+ case GPBTypeFixed32:
+ case GPBTypeUInt32:
+ dict = [[GPBInt64UInt32Dictionary alloc] init];
+ break;
+ case GPBTypeInt32:
+ case GPBTypeSFixed32:
+ case GPBTypeSInt32:
+ dict = [[GPBInt64Int32Dictionary alloc] init];
+ break;
+ case GPBTypeFixed64:
+ case GPBTypeUInt64:
+ dict = [[GPBInt64UInt64Dictionary alloc] init];
+ break;
+ case GPBTypeInt64:
+ case GPBTypeSFixed64:
+ case GPBTypeSInt64:
+ dict = [[GPBInt64Int64Dictionary alloc] init];
+ break;
+ case GPBTypeFloat:
+ dict = [[GPBInt64FloatDictionary alloc] init];
+ break;
+ case GPBTypeDouble:
+ dict = [[GPBInt64DoubleDictionary alloc] init];
+ break;
+ case GPBTypeEnum:
+ dict = [[GPBInt64EnumDictionary alloc]
+ initWithValidationFunction:field.enumDescriptor.enumVerifier];
+ break;
+ case GPBTypeData:
+ case GPBTypeMessage:
+ case GPBTypeString:
+ dict = [[GPBInt64ObjectDictionary alloc] init];
+ break;
+ case GPBTypeGroup:
+ NSCAssert(NO, @"shouldn't happen");
+ return nil;
+ }
+ break;
+ case GPBTypeString:
+ switch (valueType) {
+ case GPBTypeBool:
+ dict = [[GPBStringBoolDictionary alloc] init];
+ break;
+ case GPBTypeFixed32:
+ case GPBTypeUInt32:
+ dict = [[GPBStringUInt32Dictionary alloc] init];
+ break;
+ case GPBTypeInt32:
+ case GPBTypeSFixed32:
+ case GPBTypeSInt32:
+ dict = [[GPBStringInt32Dictionary alloc] init];
+ break;
+ case GPBTypeFixed64:
+ case GPBTypeUInt64:
+ dict = [[GPBStringUInt64Dictionary alloc] init];
+ break;
+ case GPBTypeInt64:
+ case GPBTypeSFixed64:
+ case GPBTypeSInt64:
+ dict = [[GPBStringInt64Dictionary alloc] init];
+ break;
+ case GPBTypeFloat:
+ dict = [[GPBStringFloatDictionary alloc] init];
+ break;
+ case GPBTypeDouble:
+ dict = [[GPBStringDoubleDictionary alloc] init];
+ break;
+ case GPBTypeEnum:
+ dict = [[GPBStringEnumDictionary alloc]
+ initWithValidationFunction:field.enumDescriptor.enumVerifier];
+ break;
+ case GPBTypeData:
+ case GPBTypeMessage:
+ case GPBTypeString:
+ dict = [[NSMutableDictionary alloc] init];
+ break;
+ case GPBTypeGroup:
+ NSCAssert(NO, @"shouldn't happen");
+ return nil;
+ }
+ break;
+
+ case GPBTypeFloat:
+ case GPBTypeDouble:
+ case GPBTypeEnum:
+ case GPBTypeData:
+ case GPBTypeGroup:
+ case GPBTypeMessage:
+ NSCAssert(NO, @"shouldn't happen");
+ return nil;
+ }
+
+ GPBSetRetainedObjectIvarWithFieldInternal(self, field, dict, syntax);
+ }
+ return dict;
+}
+
+#endif // !defined(__clang_analyzer__)
+
+GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass,
+ GPBMessage *autocreator,
+ GPBFieldDescriptor *field) {
+ GPBMessage *message = [[msgClass alloc] init];
+ message->autocreator_ = autocreator;
+ message->autocreatorField_ = [field retain];
+ return message;
+}
+
+static GPBMessage *CreateMessageWithAutocreatorForExtension(
+ Class msgClass, GPBMessage *autocreator, GPBExtensionField *extension)
+ __attribute__((ns_returns_retained));
+
+static GPBMessage *CreateMessageWithAutocreatorForExtension(
+ Class msgClass, GPBMessage *autocreator, GPBExtensionField *extension) {
+ GPBMessage *message = [[msgClass alloc] init];
+ message->autocreator_ = autocreator;
+ message->autocreatorExtension_ = [extension retain];
+ return message;
+}
+
+BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent) {
+ return (message->autocreator_ == parent);
+}
+
+void GPBBecomeVisibleToAutocreator(GPBMessage *self) {
+ // Message objects that are implicitly created by accessing a message field
+ // are initially not visible via the hasX selector. This method makes them
+ // visible.
+ if (self->autocreator_) {
+ // This will recursively make all parent messages visible until it reaches a
+ // super-creator that's visible.
+ if (self->autocreatorField_) {
+ GPBFileSyntax syntax = [self->autocreator_ descriptor].file.syntax;
+ GPBSetObjectIvarWithFieldInternal(self->autocreator_,
+ self->autocreatorField_, self, syntax);
+ } else {
+ [self->autocreator_ setExtension:self->autocreatorExtension_ value:self];
+ }
+ }
+}
+
+void GPBAutocreatedArrayModified(GPBMessage *self, id array) {
+ // When one of our autocreated arrays adds elements, make it visible.
+ GPBDescriptor *descriptor = [[self class] descriptor];
+ for (GPBFieldDescriptor *field in descriptor->fields_) {
+ if (field.fieldType == GPBFieldTypeRepeated) {
+ id curArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (curArray == array) {
+ if (GPBFieldTypeIsObject(field)) {
+ GPBAutocreatedArray *autoArray = array;
+ autoArray->_autocreator = nil;
+ } else {
+ GPBInt32Array *gpbArray = array;
+ gpbArray->_autocreator = nil;
+ }
+ GPBBecomeVisibleToAutocreator(self);
+ return;
+ }
+ }
+ }
+ NSCAssert(NO, @"Unknown array.");
+}
+
+void GPBClearMessageAutocreator(GPBMessage *self) {
+ if ((self == nil) || !self->autocreator_) {
+ return;
+ }
+
+#if DEBUG && !defined(NS_BLOCK_ASSERTIONS)
+ // Either the autocreator must have its "has" flag set to YES, or it must be
+ // NO and not equal to ourselves.
+ BOOL autocreatorHas =
+ (self->autocreatorField_
+ ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_)
+ : [self->autocreator_ hasExtension:self->autocreatorExtension_]);
+ GPBMessage *autocreatorFieldValue =
+ (self->autocreatorField_
+ ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_,
+ self->autocreatorField_)
+ : [self->autocreator_->autocreatedExtensionMap_
+ objectForKey:self->autocreatorExtension_]);
+ NSCAssert(autocreatorHas || autocreatorFieldValue != self,
+ @"Cannot clear autocreator because it still refers to self.");
+
+#endif // DEBUG && !defined(NS_BLOCK_ASSERTIONS)
+
+ self->autocreator_ = nil;
+ [self->autocreatorField_ release];
+ self->autocreatorField_ = nil;
+ [self->autocreatorExtension_ release];
+ self->autocreatorExtension_ = nil;
+}
+
+static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
+ if (!self->unknownFields_) {
+ self->unknownFields_ = [[GPBUnknownFieldSet alloc] init];
+ GPBBecomeVisibleToAutocreator(self);
+ }
+ return self->unknownFields_;
+}
+
+#ifdef DEBUG
+static void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) {
+ if (!message.initialized) {
+ NSString *reason =
+ [NSString stringWithFormat:@"Uninitialized Message %@", message];
+ NSDictionary *userInfo =
+ message ? @{GPBExceptionMessageKey : message} : nil;
+ NSException *exception =
+ [NSException exceptionWithName:NSInternalInconsistencyException
+ reason:reason
+ userInfo:userInfo];
+ [exception raise];
+ }
+}
+#else
+GPB_INLINE void DebugRaiseExceptionIfNotInitialized(GPBMessage *message) {
+#pragma unused(message)
+}
+#endif // DEBUG
+
+@implementation GPBMessage
+
++ (void)initialize {
+ Class pbMessageClass = [GPBMessage class];
+ if ([self class] == pbMessageClass) {
+ // This is here to start up the "base" class descriptor.
+ [self descriptor];
+ } else if ([self superclass] == pbMessageClass) {
+ // This is here to start up all the "message" subclasses. Just needs to be
+ // done for the messages, not any of the subclasses.
+ // This must be done in initialize to enforce thread safety of start up of
+ // the protocol buffer library. All of the extension registries must be
+ // created in either "+load" or "+initialize".
+ [self descriptor];
+ [self extensionRegistry];
+ }
+}
+
++ (instancetype)allocWithZone:(NSZone *)zone {
+ // Override alloc to allocate our classes with the additional storage
+ // required for the instance variables.
+ GPBDescriptor *descriptor = [self descriptor];
+ return NSAllocateObject(self, descriptor->storageSize_, zone);
+}
+
++ (instancetype)alloc {
+ return [self allocWithZone:nil];
+}
+
++ (GPBDescriptor *)descriptor {
+ // This is thread safe because it is called from +initialize.
+ static GPBDescriptor *descriptor = NULL;
+ static GPBFileDescriptor *fileDescriptor = NULL;
+ if (!descriptor) {
+ // Use a dummy file that marks it as proto2 syntax so when used generically
+ // it supports unknowns/etc.
+ fileDescriptor =
+ [[GPBFileDescriptor alloc] initWithPackage:@"internal"
+ syntax:GPBFileSyntaxProto2];
+
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class]
+ rootClass:Nil
+ file:fileDescriptor
+ fields:NULL
+ fieldCount:0
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:0
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
++ (instancetype)message {
+ return [[[self alloc] init] autorelease];
+}
+
+- (instancetype)init {
+ if ((self = [super init])) {
+ messageStorage_ = (GPBMessage_StoragePtr)(
+ ((uint8_t *)self) + class_getInstanceSize([self class]));
+
+ readOnlyMutex_ = OS_SPINLOCK_INIT;
+ }
+
+ return self;
+}
+
+- (instancetype)initWithData:(NSData *)data {
+ return [self initWithData:data extensionRegistry:nil];
+}
+
+- (instancetype)initWithData:(NSData *)data
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+ if ((self = [self init])) {
+ [self mergeFromData:data extensionRegistry:extensionRegistry];
+ DebugRaiseExceptionIfNotInitialized(self);
+ }
+ return self;
+}
+
+- (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:
+ (GPBExtensionRegistry *)extensionRegistry {
+ if ((self = [self init])) {
+ [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
+ DebugRaiseExceptionIfNotInitialized(self);
+ }
+ return self;
+}
+
+- (void)dealloc {
+ [self internalClear:NO];
+ NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc.");
+ [super dealloc];
+}
+
+- (void)copyFieldsInto:(GPBMessage *)message
+ zone:(NSZone *)zone
+ descriptor:(GPBDescriptor *)descriptor {
+ // Copy all the storage...
+ memcpy(message->messageStorage_, messageStorage_, descriptor->storageSize_);
+
+ GPBFileSyntax syntax = descriptor.file.syntax;
+
+ // Loop over the fields doing fixup...
+ for (GPBFieldDescriptor *field in descriptor->fields_) {
+ if (GPBFieldIsMapOrArray(field)) {
+ id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (value) {
+ // We need to copy the array/map, but the catch is for message fields,
+ // we also need to ensure all the messages as those need copying also.
+ id newValue;
+ if (GPBFieldTypeIsMessage(field)) {
+ if (field.fieldType == GPBFieldTypeRepeated) {
+ NSArray *existingArray = (NSArray *)value;
+ NSMutableArray *newArray =
+ [[NSMutableArray alloc] initWithCapacity:existingArray.count];
+ newValue = newArray;
+ for (GPBMessage *msg in existingArray) {
+ GPBMessage *copiedMsg = [msg copyWithZone:zone];
+ [newArray addObject:copiedMsg];
+ [copiedMsg release];
+ }
+ } else {
+ if (field.mapKeyType == GPBTypeString) {
+ // Map is an NSDictionary.
+ NSDictionary *existingDict = value;
+ NSMutableDictionary *newDict = [[NSMutableDictionary alloc]
+ initWithCapacity:existingDict.count];
+ newValue = newDict;
+ [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key,
+ GPBMessage *msg,
+ BOOL *stop) {
+#pragma unused(stop)
+ GPBMessage *copiedMsg = [msg copyWithZone:zone];
+ [newDict setObject:copiedMsg forKey:key];
+ [copiedMsg release];
+ }];
+ } else {
+ // Is one of the GPB*ObjectDictionary classes. Type doesn't
+ // matter, just need one to invoke the selector.
+ GPBInt32ObjectDictionary *existingDict = value;
+ newValue = [existingDict deepCopyWithZone:zone];
+ }
+ }
+ } else {
+ // Not messages (but is a map/array)...
+ if (field.fieldType == GPBFieldTypeRepeated) {
+ if (GPBFieldTypeIsObject(field)) {
+ // NSArray
+ newValue = [value mutableCopyWithZone:zone];
+ } else {
+ // GPB*Array
+ newValue = [value copyWithZone:zone];
+ }
+ } else {
+ if (field.mapKeyType == GPBTypeString) {
+ // NSDictionary
+ newValue = [value mutableCopyWithZone:zone];
+ } else {
+ // Is one of the GPB*Dictionary classes. Type doesn't matter,
+ // just need one to invoke the selector.
+ GPBInt32Int32Dictionary *existingDict = value;
+ newValue = [existingDict copyWithZone:zone];
+ }
+ }
+ }
+ // We retain here because the memcpy picked up the pointer value and
+ // the next call to SetRetainedObject... will release the current value.
+ [value retain];
+ GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
+ syntax);
+ }
+ } else if (GPBFieldTypeIsMessage(field)) {
+ // For object types, if we have a value, copy it. If we don't,
+ // zero it to remove the pointer to something that was autocreated
+ // (and the ptr just got memcpyed).
+ if (GPBGetHasIvarField(self, field)) {
+ GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ GPBMessage *newValue = [value copyWithZone:zone];
+ // We retain here because the memcpy picked up the pointer value and
+ // the next call to SetRetainedObject... will release the current value.
+ [value retain];
+ GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
+ syntax);
+ } else {
+ uint8_t *storage = (uint8_t *)message->messageStorage_;
+ id *typePtr = (id *)&storage[field->description_->offset];
+ *typePtr = NULL;
+ }
+ } else if (GPBFieldTypeIsObject(field) && GPBGetHasIvarField(self, field)) {
+ // A set string/data value (message picked off above), copy it.
+ id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ id newValue = [value copyWithZone:zone];
+ // We retain here because the memcpy picked up the pointer value and
+ // the next call to SetRetainedObject... will release the current value.
+ [value retain];
+ GPBSetRetainedObjectIvarWithFieldInternal(message, field, newValue,
+ syntax);
+ } else {
+ // memcpy took care of the rest of the primative fields if they were set.
+ }
+ } // for (field in descriptor->fields_)
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+ GPBDescriptor *descriptor = [self descriptor];
+ GPBMessage *result = [[descriptor.messageClass allocWithZone:zone] init];
+
+ [self copyFieldsInto:result zone:zone descriptor:descriptor];
+ // Make immutable copies of the extra bits.
+ result->unknownFields_ = [unknownFields_ copyWithZone:zone];
+ result->extensionMap_ = CloneExtensionMap(extensionMap_, zone);
+ return result;
+}
+
+- (void)clear {
+ [self internalClear:YES];
+}
+
+- (void)internalClear:(BOOL)zeroStorage {
+ GPBDescriptor *descriptor = [self descriptor];
+ for (GPBFieldDescriptor *field in descriptor->fields_) {
+ if (GPBFieldIsMapOrArray(field)) {
+ id arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (arrayOrMap) {
+ if (field.fieldType == GPBFieldTypeRepeated) {
+ if (GPBFieldTypeIsObject(field)) {
+ GPBAutocreatedArray *autoArray = arrayOrMap;
+ if (autoArray->_autocreator == self) {
+ autoArray->_autocreator = nil;
+ }
+ } else {
+ // Type doesn't matter, it is a GPB*Array.
+ GPBInt32Array *gpbArray = arrayOrMap;
+ if (gpbArray->_autocreator == self) {
+ gpbArray->_autocreator = nil;
+ }
+ }
+ }
+ [arrayOrMap release];
+ }
+ } else if (GPBFieldTypeIsMessage(field)) {
+ GPBClearAutocreatedMessageIvarWithField(self, field);
+ GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [value release];
+ } else if (GPBFieldTypeIsObject(field) && GPBGetHasIvarField(self, field)) {
+ id value = GPBGetObjectIvarWithField(self, field);
+ [value release];
+ }
+ }
+
+ // GPBClearMessageAutocreator() expects that its caller has already been
+ // removed from autocreatedExtensionMap_ so we set to nil first.
+ NSArray *autocreatedValues = [autocreatedExtensionMap_ allValues];
+ [autocreatedExtensionMap_ release];
+ autocreatedExtensionMap_ = nil;
+
+ // Since we're clearing all of our extensions, make sure that we clear the
+ // autocreator on any that we've created so they no longer refer to us.
+ for (GPBMessage *value in autocreatedValues) {
+ NSCAssert(GPBWasMessageAutocreatedBy(value, self),
+ @"Autocreated extension does not refer back to self.");
+ GPBClearMessageAutocreator(value);
+ }
+
+ [extensionMap_ release];
+ extensionMap_ = nil;
+ [unknownFields_ release];
+ unknownFields_ = nil;
+
+ // Note that clearing does not affect autocreator_. If we are being cleared
+ // because of a dealloc, then autocreator_ should be nil anyway. If we are
+ // being cleared because someone explicitly clears us, we don't want to
+ // sever our relationship with our autocreator.
+
+ if (zeroStorage) {
+ memset(messageStorage_, 0, descriptor->storageSize_);
+ }
+}
+
+- (BOOL)isInitialized {
+ GPBDescriptor *descriptor = [self descriptor];
+ for (GPBFieldDescriptor *field in descriptor->fields_) {
+ if (field.isRequired) {
+ if (!GPBGetHasIvarField(self, field)) {
+ return NO;
+ }
+ }
+ if (GPBFieldTypeIsMessage(field)) {
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeSingle) {
+ if (field.isRequired) {
+ GPBMessage *message = GPBGetMessageIvarWithField(self, field);
+ if (!message.initialized) {
+ return NO;
+ }
+ } else {
+ NSAssert(field.isOptional,
+ @"If not required or optional, what was it?");
+ if (GPBGetHasIvarField(self, field)) {
+ GPBMessage *message = GPBGetMessageIvarWithField(self, field);
+ if (!message.initialized) {
+ return NO;
+ }
+ }
+ }
+ } else if (fieldType == GPBFieldTypeRepeated) {
+ NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ for (GPBMessage *message in array) {
+ if (!message.initialized) {
+ return NO;
+ }
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ if (field.mapKeyType == GPBTypeString) {
+ NSDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) {
+ return NO;
+ }
+ } else {
+ // Real type is GPB*ObjectDictionary, exact type doesn't matter.
+ GPBInt32ObjectDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (map && ![map isInitialized]) {
+ return NO;
+ }
+ }
+ }
+ }
+ }
+
+ __block BOOL result = YES;
+ [extensionMap_
+ enumerateKeysAndObjectsUsingBlock:^(GPBExtensionField *extension, id obj,
+ BOOL *stop) {
+ GPBExtensionDescriptor *extDesc = extension.descriptor;
+ if (GPBExtensionIsMessage(extDesc)) {
+ if (extDesc.isRepeated) {
+ for (GPBMessage *msg in obj) {
+ if (!msg.initialized) {
+ result = NO;
+ *stop = YES;
+ break;
+ }
+ }
+ } else {
+ GPBMessage *asMsg = obj;
+ if (!asMsg.initialized) {
+ result = NO;
+ *stop = YES;
+ }
+ }
+ }
+ }];
+ return result;
+}
+
+- (GPBDescriptor *)descriptor {
+ return [[self class] descriptor];
+}
+
+- (NSData *)data {
+ DebugRaiseExceptionIfNotInitialized(self);
+ NSMutableData *data = [NSMutableData dataWithLength:[self serializedSize]];
+ GPBCodedOutputStream *stream =
+ [[GPBCodedOutputStream alloc] initWithData:data];
+ [self writeToCodedOutputStream:stream];
+ [stream release];
+ return data;
+}
+
+- (NSData *)delimitedData {
+ size_t serializedSize = [self serializedSize];
+ size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize);
+ NSMutableData *data =
+ [NSMutableData dataWithLength:(serializedSize + varintSize)];
+ GPBCodedOutputStream *stream =
+ [[GPBCodedOutputStream alloc] initWithData:data];
+ [self writeDelimitedToCodedOutputStream:stream];
+ [stream release];
+ return data;
+}
+
+- (void)writeToOutputStream:(NSOutputStream *)output {
+ GPBCodedOutputStream *stream =
+ [[GPBCodedOutputStream alloc] initWithOutputStream:output];
+ [self writeToCodedOutputStream:stream];
+ [stream release];
+}
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output {
+ GPBDescriptor *descriptor = [self descriptor];
+ NSArray *fieldsArray = descriptor->fields_;
+ NSUInteger fieldCount = fieldsArray.count;
+ const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
+ NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
+ for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
+ if (i == fieldCount) {
+ [self writeExtensionsToCodedOutputStream:output
+ range:extensionRanges[j++]];
+ } else if (j == extensionRangesCount ||
+ GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
+ [self writeField:fieldsArray[i++] toCodedOutputStream:output];
+ } else {
+ [self writeExtensionsToCodedOutputStream:output
+ range:extensionRanges[j++]];
+ }
+ }
+ if (descriptor.isWireFormat) {
+ [unknownFields_ writeAsMessageSetTo:output];
+ } else {
+ [unknownFields_ writeToCodedOutputStream:output];
+ }
+}
+
+- (void)writeDelimitedToOutputStream:(NSOutputStream *)output {
+ GPBCodedOutputStream *codedOutput =
+ [[GPBCodedOutputStream alloc] initWithOutputStream:output];
+ [self writeDelimitedToCodedOutputStream:codedOutput];
+ [codedOutput release];
+}
+
+- (void)writeDelimitedToCodedOutputStream:(GPBCodedOutputStream *)output {
+ [output writeRawVarintSizeTAs32:[self serializedSize]];
+ [self writeToCodedOutputStream:output];
+}
+
+- (void)writeField:(GPBFieldDescriptor *)field
+ toCodedOutputStream:(GPBCodedOutputStream *)output {
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeSingle) {
+ BOOL has = GPBGetHasIvarField(self, field);
+ if (!has) {
+ return;
+ }
+ }
+ uint32_t fieldNumber = GPBFieldNumber(field);
+
+//%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE)
+//%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE)
+//%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE)
+//% case GPBType##TYPE:
+//% if (fieldType == GPBFieldTypeRepeated) {
+//% uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+//% GPB##ARRAY_TYPE##Array *array =
+//% GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+//% [output write##TYPE##s:fieldNumber values:array tag:tag];
+//% } else if (fieldType == GPBFieldTypeSingle) {
+//% [output write##TYPE:fieldNumber
+//% TYPE$S value:GPBGet##REAL_TYPE##IvarWithField(self, field)];
+//% } else { // fieldType == GPBFieldTypeMap
+//% // Exact type here doesn't matter.
+//% GPBInt32##ARRAY_TYPE##Dictionary *dict =
+//% GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+//% [dict writeToCodedOutputStream:output asField:field];
+//% }
+//% break;
+//%
+//%PDDM-DEFINE FIELD_CASE2(TYPE)
+//% case GPBType##TYPE:
+//% if (fieldType == GPBFieldTypeRepeated) {
+//% NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+//% [output write##TYPE##s:fieldNumber values:array];
+//% } else if (fieldType == GPBFieldTypeSingle) {
+//% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+//% // again.
+//% [output write##TYPE:fieldNumber
+//% TYPE$S value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+//% } else { // fieldType == GPBFieldTypeMap
+//% // Exact type here doesn't matter.
+//% id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+//% GPBType mapKeyType = field.mapKeyType;
+//% if (mapKeyType == GPBTypeString) {
+//% GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
+//% } else {
+//% [dict writeToCodedOutputStream:output asField:field];
+//% }
+//% }
+//% break;
+//%
+
+ switch (GPBGetFieldType(field)) {
+
+//%PDDM-EXPAND FIELD_CASE(Bool, Bool)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeBool:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBBoolArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeBools:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeBool:fieldNumber
+ value:GPBGetBoolIvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32BoolDictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeFixed32:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBUInt32Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeFixed32s:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeFixed32:fieldNumber
+ value:GPBGetUInt32IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32UInt32Dictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(SFixed32, Int32)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeSFixed32:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBInt32Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeSFixed32s:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeSFixed32:fieldNumber
+ value:GPBGetInt32IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32Int32Dictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(Float, Float)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeFloat:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBFloatArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeFloats:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeFloat:fieldNumber
+ value:GPBGetFloatIvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32FloatDictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeFixed64:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBUInt64Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeFixed64s:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeFixed64:fieldNumber
+ value:GPBGetUInt64IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32UInt64Dictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(SFixed64, Int64)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeSFixed64:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBInt64Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeSFixed64s:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeSFixed64:fieldNumber
+ value:GPBGetInt64IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32Int64Dictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(Double, Double)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeDouble:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBDoubleArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeDoubles:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeDouble:fieldNumber
+ value:GPBGetDoubleIvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32DoubleDictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(Int32, Int32)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeInt32:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBInt32Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeInt32s:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeInt32:fieldNumber
+ value:GPBGetInt32IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32Int32Dictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(Int64, Int64)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeInt64:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBInt64Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeInt64s:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeInt64:fieldNumber
+ value:GPBGetInt64IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32Int64Dictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(SInt32, Int32)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeSInt32:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBInt32Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeSInt32s:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeSInt32:fieldNumber
+ value:GPBGetInt32IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32Int32Dictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(SInt64, Int64)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeSInt64:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBInt64Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeSInt64s:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeSInt64:fieldNumber
+ value:GPBGetInt64IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32Int64Dictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(UInt32, UInt32)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeUInt32:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBUInt32Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeUInt32s:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeUInt32:fieldNumber
+ value:GPBGetUInt32IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32UInt32Dictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE(UInt64, UInt64)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeUInt64:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBUInt64Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeUInt64s:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeUInt64:fieldNumber
+ value:GPBGetUInt64IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32UInt64Dictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeEnum:
+ if (fieldType == GPBFieldTypeRepeated) {
+ uint32_t tag = field.isPackable ? GPBFieldTag(field) : 0;
+ GPBEnumArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeEnums:fieldNumber values:array tag:tag];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ [output writeEnum:fieldNumber
+ value:GPBGetInt32IvarWithField(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ GPBInt32EnumDictionary *dict =
+ GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE2(Data)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeData:
+ if (fieldType == GPBFieldTypeRepeated) {
+ NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeDatas:fieldNumber values:array];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+ // again.
+ [output writeData:fieldNumber
+ value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ GPBType mapKeyType = field.mapKeyType;
+ if (mapKeyType == GPBTypeString) {
+ GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
+ } else {
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE2(String)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeString:
+ if (fieldType == GPBFieldTypeRepeated) {
+ NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeStrings:fieldNumber values:array];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+ // again.
+ [output writeString:fieldNumber
+ value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ GPBType mapKeyType = field.mapKeyType;
+ if (mapKeyType == GPBTypeString) {
+ GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
+ } else {
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE2(Message)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeMessage:
+ if (fieldType == GPBFieldTypeRepeated) {
+ NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeMessages:fieldNumber values:array];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+ // again.
+ [output writeMessage:fieldNumber
+ value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ GPBType mapKeyType = field.mapKeyType;
+ if (mapKeyType == GPBTypeString) {
+ GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
+ } else {
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ }
+ break;
+
+//%PDDM-EXPAND FIELD_CASE2(Group)
+// This block of code is generated, do not edit it directly.
+
+ case GPBTypeGroup:
+ if (fieldType == GPBFieldTypeRepeated) {
+ NSArray *array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ [output writeGroups:fieldNumber values:array];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+ // again.
+ [output writeGroup:fieldNumber
+ value:GPBGetObjectIvarWithFieldNoAutocreate(self, field)];
+ } else { // fieldType == GPBFieldTypeMap
+ // Exact type here doesn't matter.
+ id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ GPBType mapKeyType = field.mapKeyType;
+ if (mapKeyType == GPBTypeString) {
+ GPBDictionaryWriteToStreamInternalHelper(output, dict, field);
+ } else {
+ [dict writeToCodedOutputStream:output asField:field];
+ }
+ }
+ break;
+
+//%PDDM-EXPAND-END (18 expansions)
+ }
+}
+
+#pragma mark - Extensions
+
+- (id)getExtension:(GPBExtensionField *)extension {
+ CheckExtension(self, extension);
+ id value = [extensionMap_ objectForKey:extension];
+ if (value != nil) {
+ return value;
+ }
+
+ GPBExtensionDescriptor *extDesc = extension.descriptor;
+
+ // No default for repeated.
+ if (extDesc.isRepeated) {
+ return nil;
+ }
+ // Non messages get their default.
+ if (!GPBExtensionIsMessage(extDesc)) {
+ return [extension defaultValue];
+ }
+
+ // Check for an autocreated value.
+ OSSpinLockLock(&readOnlyMutex_);
+ value = [autocreatedExtensionMap_ objectForKey:extension];
+ if (!value) {
+ // Auto create the message extensions to match normal fields.
+ value = CreateMessageWithAutocreatorForExtension(extDesc.msgClass, self,
+ extension);
+
+ if (autocreatedExtensionMap_ == nil) {
+ autocreatedExtensionMap_ = [[NSMutableDictionary alloc] init];
+ }
+
+ // We can't simply call setExtension here because that would clear the new
+ // value's autocreator.
+ [autocreatedExtensionMap_ setObject:value forKey:extension];
+ [value release];
+ }
+
+ OSSpinLockUnlock(&readOnlyMutex_);
+ return value;
+}
+
+- (id)getExistingExtension:(GPBExtensionField *)extension {
+ // This is an internal method so we don't need to call CheckExtension().
+ return [extensionMap_ objectForKey:extension];
+}
+
+- (BOOL)hasExtension:(GPBExtensionField *)extension {
+#if DEBUG
+ CheckExtension(self, extension);
+#endif // DEBUG
+ return nil != [extensionMap_ objectForKey:extension];
+}
+
+- (NSArray *)extensionsCurrentlySet {
+ return [extensionMap_ allKeys];
+}
+
+- (void)writeExtensionsToCodedOutputStream:(GPBCodedOutputStream *)output
+ range:(GPBExtensionRange)range {
+ NSArray *sortedExtensions = [[extensionMap_ allKeys]
+ sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
+ uint32_t start = range.start;
+ uint32_t end = range.end;
+ for (GPBExtensionField *extension in sortedExtensions) {
+ uint32_t fieldNumber = [extension fieldNumber];
+ if (fieldNumber >= start && fieldNumber < end) {
+ id value = [extensionMap_ objectForKey:extension];
+ [extension writeValue:value includingTagToCodedOutputStream:output];
+ }
+ }
+}
+
+- (NSArray *)sortedExtensionsInUse {
+ return [[extensionMap_ allKeys]
+ sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
+}
+
+- (void)setExtension:(GPBExtensionField *)extension value:(id)value {
+ if (!value) {
+ [self clearExtension:extension];
+ return;
+ }
+
+ CheckExtension(self, extension);
+
+ if ([extension isRepeated]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Must call addExtension() for repeated types."];
+ }
+
+ if (extensionMap_ == nil) {
+ extensionMap_ = [[NSMutableDictionary alloc] init];
+ }
+
+ [extensionMap_ setObject:value forKey:extension];
+
+ GPBExtensionDescriptor *descriptor = extension.descriptor;
+
+ if (GPBExtensionIsMessage(descriptor) && !descriptor.isRepeated) {
+ GPBMessage *autocreatedValue =
+ [[autocreatedExtensionMap_ objectForKey:extension] retain];
+ // Must remove from the map before calling GPBClearMessageAutocreator() so
+ // that GPBClearMessageAutocreator() knows its safe to clear.
+ [autocreatedExtensionMap_ removeObjectForKey:extension];
+ GPBClearMessageAutocreator(autocreatedValue);
+ [autocreatedValue release];
+ }
+
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+- (void)addExtension:(GPBExtensionField *)extension value:(id)value {
+ CheckExtension(self, extension);
+
+ if (![extension isRepeated]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Must call setExtension() for singular types."];
+ }
+
+ if (extensionMap_ == nil) {
+ extensionMap_ = [[NSMutableDictionary alloc] init];
+ }
+ NSMutableArray *list = [extensionMap_ objectForKey:extension];
+ if (list == nil) {
+ list = [NSMutableArray array];
+ [extensionMap_ setObject:list forKey:extension];
+ }
+
+ [list addObject:value];
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+- (void)setExtension:(GPBExtensionField *)extension
+ index:(NSUInteger)idx
+ value:(id)value {
+ CheckExtension(self, extension);
+
+ if (![extension isRepeated]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Must call setExtension() for singular types."];
+ }
+
+ if (extensionMap_ == nil) {
+ extensionMap_ = [[NSMutableDictionary alloc] init];
+ }
+
+ NSMutableArray *list = [extensionMap_ objectForKey:extension];
+
+ [list replaceObjectAtIndex:idx withObject:value];
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+- (void)clearExtension:(GPBExtensionField *)extension {
+ CheckExtension(self, extension);
+
+ // Only become visible if there was actually a value to clear.
+ if ([extensionMap_ objectForKey:extension]) {
+ [extensionMap_ removeObjectForKey:extension];
+ GPBBecomeVisibleToAutocreator(self);
+ }
+}
+
+#pragma mark - mergeFrom
+
+- (void)mergeFromData:(NSData *)data
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+ GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
+ [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
+ [input checkLastTagWas:0];
+ [input release];
+}
+
+#pragma mark - mergeDelimitedFrom
+
+- (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+ GPBCodedInputStreamState *state = &input->state_;
+ if (GPBCodedInputStreamIsAtEnd(state)) {
+ return;
+ }
+ NSData *data = GPBCodedInputStreamReadRetainedDataNoCopy(state);
+ if (data == nil) {
+ return;
+ }
+ [self mergeFromData:data extensionRegistry:extensionRegistry];
+ [data release];
+}
+
+#pragma mark - Parse From Data Support
+
++ (instancetype)parseFromData:(NSData *)data {
+ return [self parseFromData:data extensionRegistry:nil];
+}
+
++ (instancetype)parseFromData:(NSData *)data
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+ return [[[self alloc] initWithData:data
+ extensionRegistry:extensionRegistry] autorelease];
+}
+
++ (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+ return
+ [[[self alloc] initWithCodedInputStream:input
+ extensionRegistry:extensionRegistry] autorelease];
+}
+
+#pragma mark - Parse Delimited From Data Support
+
++ (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:
+ (GPBExtensionRegistry *)extensionRegistry {
+ GPBMessage *message = [[[self alloc] init] autorelease];
+ [message mergeDelimitedFromCodedInputStream:input
+ extensionRegistry:extensionRegistry];
+ DebugRaiseExceptionIfNotInitialized(message);
+ return message;
+}
+
+#pragma mark - Unknown Field Support
+
+- (GPBUnknownFieldSet *)unknownFields {
+ return unknownFields_;
+}
+
+- (void)setUnknownFields:(GPBUnknownFieldSet *)unknownFields {
+ if (unknownFields != unknownFields_) {
+ [unknownFields_ release];
+ unknownFields_ = [unknownFields copy];
+ GPBBecomeVisibleToAutocreator(self);
+ }
+}
+
+- (void)parseMessageSet:(GPBCodedInputStream *)input
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+ uint32_t typeId = 0;
+ NSData *rawBytes = nil;
+ GPBExtensionField *extension = nil;
+ GPBCodedInputStreamState *state = &input->state_;
+ while (true) {
+ uint32_t tag = GPBCodedInputStreamReadTag(state);
+ if (tag == 0) {
+ break;
+ }
+
+ if (tag == GPBWireFormatMessageSetTypeIdTag) {
+ typeId = GPBCodedInputStreamReadUInt32(state);
+ if (typeId != 0) {
+ extension = [extensionRegistry getExtension:[self descriptor]
+ fieldNumber:typeId];
+ }
+ } else if (tag == GPBWireFormatMessageSetMessageTag) {
+ rawBytes = [GPBCodedInputStreamReadRetainedDataNoCopy(state) autorelease];
+ } else {
+ if (![input skipField:tag]) {
+ break;
+ }
+ }
+ }
+
+ [input checkLastTagWas:GPBWireFormatMessageSetItemEndTag];
+
+ if (rawBytes != nil && typeId != 0) {
+ if (extension != nil) {
+ GPBCodedInputStream *newInput =
+ [[GPBCodedInputStream alloc] initWithData:rawBytes];
+ [extension mergeFromCodedInputStream:newInput
+ extensionRegistry:extensionRegistry
+ message:self];
+ [newInput release];
+ } else {
+ GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+ [unknownFields mergeMessageSetMessage:typeId data:rawBytes];
+ }
+ }
+}
+
+- (BOOL)parseUnknownField:(GPBCodedInputStream *)input
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+ tag:(uint32_t)tag {
+ GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag);
+ int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag);
+
+ GPBDescriptor *descriptor = [self descriptor];
+ GPBExtensionField *extension =
+ [extensionRegistry getExtension:descriptor fieldNumber:fieldNumber];
+
+ if (extension == nil) {
+ if (descriptor.wireFormat && GPBWireFormatMessageSetItemTag == tag) {
+ [self parseMessageSet:input extensionRegistry:extensionRegistry];
+ return YES;
+ }
+ } else {
+ if ([extension wireType] == wireType) {
+ [extension mergeFromCodedInputStream:input
+ extensionRegistry:extensionRegistry
+ message:self];
+ return YES;
+ }
+ }
+ if ([GPBUnknownFieldSet isFieldTag:tag]) {
+ GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+ return [unknownFields mergeFieldFrom:tag input:input];
+ } else {
+ return NO;
+ }
+}
+
+- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
+ GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
+ [unknownFields addUnknownMapEntry:fieldNum value:data];
+}
+
+#pragma mark - MergeFromCodedInputStream Support
+
+typedef struct MergeFromCodedInputStreamContext {
+ GPBMessage *self;
+ GPBCodedInputStream *stream;
+ GPBMessage *result;
+ GPBExtensionRegistry *registry;
+ uint32_t tag;
+ GPBFileSyntax syntax;
+} MergeFromCodedInputStreamContext;
+
+//%PDDM-DEFINE MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(NAME, TYPE, ARRAY_TYPE)
+//%static BOOL DynamicMergeFromCodedInputStream##NAME(GPBFieldDescriptor *field,
+//% NAME$S void *voidContext) {
+//% MergeFromCodedInputStreamContext *context =
+//% (MergeFromCodedInputStreamContext *)voidContext;
+//% GPBCodedInputStreamState *state = &context->stream->state_;
+//% GPBFieldType fieldType = field.fieldType;
+//% if (fieldType == GPBFieldTypeRepeated) {
+//% GPB##ARRAY_TYPE##Array *array =
+//% GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+//% if (field.isPackable) {
+//% int32_t length = GPBCodedInputStreamReadInt32(state);
+//% size_t limit = GPBCodedInputStreamPushLimit(state, length);
+//% while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+//% TYPE val = GPBCodedInputStreamRead##NAME(state);
+//% [array addValue:val];
+//% }
+//% GPBCodedInputStreamPopLimit(state, limit);
+//% } else {
+//% TYPE val = GPBCodedInputStreamRead##NAME(state);
+//% [array addValue:val];
+//% }
+//% } else if (fieldType == GPBFieldTypeSingle) {
+//% TYPE val = GPBCodedInputStreamRead##NAME(state);
+//% GPBSet##ARRAY_TYPE##IvarWithFieldInternal(context->result, field, val,
+//% ARRAY_TYPE$S context->syntax);
+//% } else { // fieldType == GPBFieldTypeMap
+//% // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+//% GPBInt32Int32Dictionary *map =
+//% GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+//% [context->stream readMapEntry:map
+//% extensionRegistry:nil
+//% field:field
+//% parentMessage:context->result];
+//% }
+//% return NO;
+//%}
+//%
+//%PDDM-DEFINE MERGE_FROM_CODED_INPUT_STREAM_OBJ_FUNC(NAME)
+//%static BOOL DynamicMergeFromCodedInputStream##NAME(GPBFieldDescriptor *field,
+//% NAME$S void *voidContext) {
+//% MergeFromCodedInputStreamContext *context = voidContext;
+//% GPBCodedInputStreamState *state = &context->stream->state_;
+//% GPBFieldType fieldType = field.fieldType;
+//% if (fieldType == GPBFieldTypeMap) {
+//% // GPB*Dictionary or NSDictionary, exact type doesn't matter at this point.
+//% id map =
+//% GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+//% [context->stream readMapEntry:map
+//% extensionRegistry:nil
+//% field:field
+//% parentMessage:context->result];
+//% } else {
+//% id val = GPBCodedInputStreamReadRetained##NAME(state);
+//% if (fieldType == GPBFieldTypeRepeated) {
+//% NSMutableArray *array =
+//% GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+//% [array addObject:val];
+//% [val release];
+//% } else { // fieldType == GPBFieldTypeSingle
+//% GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, val,
+//% context->syntax);
+//% }
+//% }
+//% return NO;
+//%}
+//%
+
+static BOOL DynamicMergeFromCodedInputStreamGroup(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ int number = GPBFieldNumber(field);
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBMessage *message = [[field.msgClass alloc] init];
+ NSMutableArray *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ [context->stream readGroup:number
+ message:message
+ extensionRegistry:context->registry];
+ [array addObject:message];
+ [message release];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL has = GPBGetHasIvarField(context->result, field);
+ if (has) {
+ // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+ // again.
+ GPBMessage *message =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->result, field);
+ [context->stream readGroup:number
+ message:message
+ extensionRegistry:context->registry];
+ } else {
+ GPBMessage *message = [[field.msgClass alloc] init];
+ [context->stream readGroup:number
+ message:message
+ extensionRegistry:context->registry];
+ GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, message,
+ context->syntax);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ NSCAssert(NO, @"Shouldn't happen");
+ return YES;
+ }
+ return NO;
+}
+
+static BOOL DynamicMergeFromCodedInputStreamMessage(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBMessage *message = [[field.msgClass alloc] init];
+ NSMutableArray *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ [context->stream readMessage:message extensionRegistry:context->registry];
+ [array addObject:message];
+ [message release];
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL has = GPBGetHasIvarField(context->result, field);
+ if (has) {
+ // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+ // again.
+ GPBMessage *message =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->result, field);
+ [context->stream readMessage:message extensionRegistry:context->registry];
+ } else {
+ GPBMessage *message = [[field.msgClass alloc] init];
+ [context->stream readMessage:message extensionRegistry:context->registry];
+ GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, message,
+ context->syntax);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // GPB*Dictionary or NSDictionary, exact type doesn't matter.
+ id map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:context->registry
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+static BOOL DynamicMergeFromCodedInputStreamEnum(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ int number = GPBFieldNumber(field);
+ BOOL hasPreservingUnknownEnumSemantics =
+ GPBHasPreservingUnknownEnumSemantics(context->syntax);
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBEnumArray *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ int32_t val = GPBCodedInputStreamReadEnum(state);
+ if (hasPreservingUnknownEnumSemantics || [field isValidEnumValue:val]) {
+ [array addRawValue:val];
+ } else {
+ GPBUnknownFieldSet *unknownFields =
+ GetOrMakeUnknownFields(context->self);
+ [unknownFields mergeVarintField:number value:val];
+ }
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ int32_t val = GPBCodedInputStreamReadEnum(state);
+ if (hasPreservingUnknownEnumSemantics || [field isValidEnumValue:val]) {
+ [array addRawValue:val];
+ } else {
+ GPBUnknownFieldSet *unknownFields =
+ GetOrMakeUnknownFields(context->self);
+ [unknownFields mergeVarintField:number value:val];
+ }
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ int32_t val = GPBCodedInputStreamReadEnum(state);
+ if (hasPreservingUnknownEnumSemantics || [field isValidEnumValue:val]) {
+ GPBSetInt32IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else {
+ GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(context->self);
+ [unknownFields mergeVarintField:number value:val];
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a
+ // GPB*EnumDictionary.
+ GPBInt32EnumDictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:context->registry
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Bool, BOOL, Bool)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamBool(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBBoolArray *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ BOOL val = GPBCodedInputStreamReadBool(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ BOOL val = GPBCodedInputStreamReadBool(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL val = GPBCodedInputStreamReadBool(state);
+ GPBSetBoolIvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Int32, int32_t, Int32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamInt32(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt32Array *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ int32_t val = GPBCodedInputStreamReadInt32(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ int32_t val = GPBCodedInputStreamReadInt32(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ int32_t val = GPBCodedInputStreamReadInt32(state);
+ GPBSetInt32IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SInt32, int32_t, Int32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamSInt32(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt32Array *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ int32_t val = GPBCodedInputStreamReadSInt32(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ int32_t val = GPBCodedInputStreamReadSInt32(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ int32_t val = GPBCodedInputStreamReadSInt32(state);
+ GPBSetInt32IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SFixed32, int32_t, Int32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamSFixed32(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt32Array *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ int32_t val = GPBCodedInputStreamReadSFixed32(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ int32_t val = GPBCodedInputStreamReadSFixed32(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ int32_t val = GPBCodedInputStreamReadSFixed32(state);
+ GPBSetInt32IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(UInt32, uint32_t, UInt32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamUInt32(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBUInt32Array *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ uint32_t val = GPBCodedInputStreamReadUInt32(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ uint32_t val = GPBCodedInputStreamReadUInt32(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ uint32_t val = GPBCodedInputStreamReadUInt32(state);
+ GPBSetUInt32IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Fixed32, uint32_t, UInt32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamFixed32(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBUInt32Array *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ uint32_t val = GPBCodedInputStreamReadFixed32(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ uint32_t val = GPBCodedInputStreamReadFixed32(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ uint32_t val = GPBCodedInputStreamReadFixed32(state);
+ GPBSetUInt32IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Int64, int64_t, Int64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamInt64(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt64Array *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ int64_t val = GPBCodedInputStreamReadInt64(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ int64_t val = GPBCodedInputStreamReadInt64(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ int64_t val = GPBCodedInputStreamReadInt64(state);
+ GPBSetInt64IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SFixed64, int64_t, Int64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamSFixed64(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt64Array *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ int64_t val = GPBCodedInputStreamReadSFixed64(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ int64_t val = GPBCodedInputStreamReadSFixed64(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ int64_t val = GPBCodedInputStreamReadSFixed64(state);
+ GPBSetInt64IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(SInt64, int64_t, Int64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamSInt64(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt64Array *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ int64_t val = GPBCodedInputStreamReadSInt64(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ int64_t val = GPBCodedInputStreamReadSInt64(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ int64_t val = GPBCodedInputStreamReadSInt64(state);
+ GPBSetInt64IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(UInt64, uint64_t, UInt64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamUInt64(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBUInt64Array *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ uint64_t val = GPBCodedInputStreamReadUInt64(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ uint64_t val = GPBCodedInputStreamReadUInt64(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ uint64_t val = GPBCodedInputStreamReadUInt64(state);
+ GPBSetUInt64IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Fixed64, uint64_t, UInt64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamFixed64(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBUInt64Array *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ uint64_t val = GPBCodedInputStreamReadFixed64(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ uint64_t val = GPBCodedInputStreamReadFixed64(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ uint64_t val = GPBCodedInputStreamReadFixed64(state);
+ GPBSetUInt64IvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Float, float, Float)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamFloat(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBFloatArray *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ float val = GPBCodedInputStreamReadFloat(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ float val = GPBCodedInputStreamReadFloat(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ float val = GPBCodedInputStreamReadFloat(state);
+ GPBSetFloatIvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_POD_FUNC(Double, double, Double)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamDouble(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context =
+ (MergeFromCodedInputStreamContext *)voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBDoubleArray *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ if (field.isPackable) {
+ int32_t length = GPBCodedInputStreamReadInt32(state);
+ size_t limit = GPBCodedInputStreamPushLimit(state, length);
+ while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+ double val = GPBCodedInputStreamReadDouble(state);
+ [array addValue:val];
+ }
+ GPBCodedInputStreamPopLimit(state, limit);
+ } else {
+ double val = GPBCodedInputStreamReadDouble(state);
+ [array addValue:val];
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ double val = GPBCodedInputStreamReadDouble(state);
+ GPBSetDoubleIvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ } else { // fieldType == GPBFieldTypeMap
+ // The exact type doesn't matter, just need to know it is a GPB*Dictionary.
+ GPBInt32Int32Dictionary *map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_OBJ_FUNC(String)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamString(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context = voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeMap) {
+ // GPB*Dictionary or NSDictionary, exact type doesn't matter at this point.
+ id map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ } else {
+ id val = GPBCodedInputStreamReadRetainedString(state);
+ if (fieldType == GPBFieldTypeRepeated) {
+ NSMutableArray *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ [array addObject:val];
+ [val release];
+ } else { // fieldType == GPBFieldTypeSingle
+ GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ }
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND MERGE_FROM_CODED_INPUT_STREAM_OBJ_FUNC(Data)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicMergeFromCodedInputStreamData(GPBFieldDescriptor *field,
+ void *voidContext) {
+ MergeFromCodedInputStreamContext *context = voidContext;
+ GPBCodedInputStreamState *state = &context->stream->state_;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeMap) {
+ // GPB*Dictionary or NSDictionary, exact type doesn't matter at this point.
+ id map =
+ GetOrCreateMapIvarWithField(context->result, field, context->syntax);
+ [context->stream readMapEntry:map
+ extensionRegistry:nil
+ field:field
+ parentMessage:context->result];
+ } else {
+ id val = GPBCodedInputStreamReadRetainedData(state);
+ if (fieldType == GPBFieldTypeRepeated) {
+ NSMutableArray *array =
+ GetOrCreateArrayIvarWithField(context->result, field, context->syntax);
+ [array addObject:val];
+ [val release];
+ } else { // fieldType == GPBFieldTypeSingle
+ GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, val,
+ context->syntax);
+ }
+ }
+ return NO;
+}
+
+//%PDDM-EXPAND-END (15 expansions)
+
+- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+ GPBDescriptor *descriptor = [self descriptor];
+ GPBFileSyntax syntax = descriptor.file.syntax;
+ MergeFromCodedInputStreamContext context = {
+ self, input, self, extensionRegistry, 0, syntax
+ };
+ GPBApplyStrictFunctions funcs =
+ GPBAPPLY_STRICT_FUNCTIONS_INIT(DynamicMergeFromCodedInputStream);
+ NSUInteger startingIndex = 0;
+ NSArray *fields = descriptor->fields_;
+ NSUInteger count = fields.count;
+ while (YES) {
+ BOOL merged = NO;
+ context.tag = GPBCodedInputStreamReadTag(&input->state_);
+ for (NSUInteger i = 0; i < count; ++i) {
+ if (startingIndex >= count) startingIndex = 0;
+ GPBFieldDescriptor *fieldDescriptor = fields[startingIndex];
+ if (GPBFieldTag(fieldDescriptor) == context.tag) {
+ GPBApplyFunction function = funcs[GPBGetFieldType(fieldDescriptor)];
+ function(fieldDescriptor, &context);
+ merged = YES;
+ break;
+ } else {
+ startingIndex += 1;
+ }
+ }
+ if (!merged) {
+ if (context.tag == 0) {
+ // zero signals EOF / limit reached
+ return;
+ } else {
+ if (GPBPreserveUnknownFields(syntax)) {
+ if (![self parseUnknownField:input
+ extensionRegistry:extensionRegistry
+ tag:context.tag]) {
+ // it's an endgroup tag
+ return;
+ }
+ } else {
+ if (![input skipField:context.tag]) {
+ return;
+ }
+ }
+ }
+ }
+ }
+}
+
+#pragma mark - MergeFrom Support
+
+typedef struct MergeFromContext {
+ GPBMessage *other;
+ GPBMessage *result;
+ GPBFileSyntax syntax;
+} MergeFromContext;
+
+//%PDDM-DEFINE GPB_MERGE_FROM_FUNC(NAME)
+//%static BOOL MergeFrom##NAME(GPBFieldDescriptor *field, void *voidContext) {
+//% MergeFromContext *context = (MergeFromContext *)voidContext;
+//% BOOL otherHas = GPBGetHasIvarField(context->other, field);
+//% if (otherHas) {
+//% GPBSet##NAME##IvarWithFieldInternal(
+//% context->result, field, GPBGet##NAME##IvarWithField(context->other, field),
+//% context->syntax);
+//% }
+//% return YES;
+//%}
+//%
+//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Bool)
+// This block of code is generated, do not edit it directly.
+
+static BOOL MergeFromBool(GPBFieldDescriptor *field, void *voidContext) {
+ MergeFromContext *context = (MergeFromContext *)voidContext;
+ BOOL otherHas = GPBGetHasIvarField(context->other, field);
+ if (otherHas) {
+ GPBSetBoolIvarWithFieldInternal(
+ context->result, field, GPBGetBoolIvarWithField(context->other, field),
+ context->syntax);
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Int32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL MergeFromInt32(GPBFieldDescriptor *field, void *voidContext) {
+ MergeFromContext *context = (MergeFromContext *)voidContext;
+ BOOL otherHas = GPBGetHasIvarField(context->other, field);
+ if (otherHas) {
+ GPBSetInt32IvarWithFieldInternal(
+ context->result, field, GPBGetInt32IvarWithField(context->other, field),
+ context->syntax);
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(UInt32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL MergeFromUInt32(GPBFieldDescriptor *field, void *voidContext) {
+ MergeFromContext *context = (MergeFromContext *)voidContext;
+ BOOL otherHas = GPBGetHasIvarField(context->other, field);
+ if (otherHas) {
+ GPBSetUInt32IvarWithFieldInternal(
+ context->result, field, GPBGetUInt32IvarWithField(context->other, field),
+ context->syntax);
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Int64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL MergeFromInt64(GPBFieldDescriptor *field, void *voidContext) {
+ MergeFromContext *context = (MergeFromContext *)voidContext;
+ BOOL otherHas = GPBGetHasIvarField(context->other, field);
+ if (otherHas) {
+ GPBSetInt64IvarWithFieldInternal(
+ context->result, field, GPBGetInt64IvarWithField(context->other, field),
+ context->syntax);
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(UInt64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL MergeFromUInt64(GPBFieldDescriptor *field, void *voidContext) {
+ MergeFromContext *context = (MergeFromContext *)voidContext;
+ BOOL otherHas = GPBGetHasIvarField(context->other, field);
+ if (otherHas) {
+ GPBSetUInt64IvarWithFieldInternal(
+ context->result, field, GPBGetUInt64IvarWithField(context->other, field),
+ context->syntax);
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Float)
+// This block of code is generated, do not edit it directly.
+
+static BOOL MergeFromFloat(GPBFieldDescriptor *field, void *voidContext) {
+ MergeFromContext *context = (MergeFromContext *)voidContext;
+ BOOL otherHas = GPBGetHasIvarField(context->other, field);
+ if (otherHas) {
+ GPBSetFloatIvarWithFieldInternal(
+ context->result, field, GPBGetFloatIvarWithField(context->other, field),
+ context->syntax);
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND GPB_MERGE_FROM_FUNC(Double)
+// This block of code is generated, do not edit it directly.
+
+static BOOL MergeFromDouble(GPBFieldDescriptor *field, void *voidContext) {
+ MergeFromContext *context = (MergeFromContext *)voidContext;
+ BOOL otherHas = GPBGetHasIvarField(context->other, field);
+ if (otherHas) {
+ GPBSetDoubleIvarWithFieldInternal(
+ context->result, field, GPBGetDoubleIvarWithField(context->other, field),
+ context->syntax);
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND-END (7 expansions)
+
+static BOOL MergeFromObject(GPBFieldDescriptor *field, void *voidContext) {
+ MergeFromContext *context = (MergeFromContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ // In the case of a list, they need to be appended, and there is no
+ // _hasIvar to worry about setting.
+ id otherArray =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->other, field);
+ if (otherArray) {
+ GPBType fieldDataType = field->description_->type;
+ if (GPBTypeIsObject(fieldDataType)) {
+ NSMutableArray *resultArray = GetOrCreateArrayIvarWithField(
+ context->result, field, context->syntax);
+ [resultArray addObjectsFromArray:otherArray];
+ } else if (fieldDataType == GPBTypeEnum) {
+ GPBEnumArray *resultArray = GetOrCreateArrayIvarWithField(
+ context->result, field, context->syntax);
+ [resultArray addRawValuesFromArray:otherArray];
+ } else {
+ // The array type doesn't matter, that all implment
+ // -addValuesFromArray:.
+ GPBInt32Array *resultArray = GetOrCreateArrayIvarWithField(
+ context->result, field, context->syntax);
+ [resultArray addValuesFromArray:otherArray];
+ }
+ }
+ return YES;
+ }
+ if (fieldType == GPBFieldTypeMap) {
+ // In the case of a map, they need to be merged, and there is no
+ // _hasIvar to worry about setting.
+ id otherDict = GPBGetObjectIvarWithFieldNoAutocreate(context->other, field);
+ if (otherDict) {
+ GPBType keyType = field.mapKeyType;
+ GPBType valueType = field->description_->type;
+ if (GPBTypeIsObject(keyType) && GPBTypeIsObject(valueType)) {
+ NSMutableDictionary *resultDict = GetOrCreateMapIvarWithField(
+ context->result, field, context->syntax);
+ [resultDict addEntriesFromDictionary:otherDict];
+ } else if (valueType == GPBTypeEnum) {
+ // The exact type doesn't matter, just need to know it is a
+ // GPB*EnumDictionary.
+ GPBInt32EnumDictionary *resultDict = GetOrCreateMapIvarWithField(
+ context->result, field, context->syntax);
+ [resultDict addRawEntriesFromDictionary:otherDict];
+ } else {
+ // The exact type doesn't matter, they all implement
+ // -addEntriesFromDictionary:.
+ GPBInt32Int32Dictionary *resultDict = GetOrCreateMapIvarWithField(
+ context->result, field, context->syntax);
+ [resultDict addEntriesFromDictionary:otherDict];
+ }
+ }
+ return YES;
+ }
+
+ int32_t hasIndex = GPBFieldHasIndex(field);
+ uint32_t fieldNumber = GPBFieldNumber(field);
+ BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNumber);
+ if (!otherHas) {
+ return YES;
+ }
+ // GPBGetObjectIvarWithFieldNoAutocreate skips the has check, faster.
+ id otherVal = GPBGetObjectIvarWithFieldNoAutocreate(context->other, field);
+ if (GPBFieldTypeIsMessage(field)) {
+ if (GPBGetHasIvar(context->result, hasIndex, fieldNumber)) {
+ GPBMessage *message =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->result, field);
+ [message mergeFrom:otherVal];
+ } else {
+ GPBMessage *message = [otherVal copy];
+ GPBSetRetainedObjectIvarWithFieldInternal(context->result, field, message,
+ context->syntax);
+ }
+ } else {
+ GPBSetObjectIvarWithFieldInternal(context->result, field, otherVal,
+ context->syntax);
+ }
+ return YES;
+}
+
+- (void)mergeFrom:(GPBMessage *)other {
+ Class selfClass = [self class];
+ Class otherClass = [other class];
+ if (!([selfClass isSubclassOfClass:otherClass] ||
+ [otherClass isSubclassOfClass:selfClass])) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Classes must match %@ != %@", selfClass, otherClass];
+ }
+
+ GPBApplyFunctions funcs = GPBAPPLY_FUNCTIONS_INIT(MergeFrom);
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ MergeFromContext context = {other, self, syntax};
+ GPBApplyFunctionsToMessageFields(&funcs, self, &context);
+
+ // We assume someting got done, and become visible.
+ GPBBecomeVisibleToAutocreator(self);
+
+ // Unknown fields.
+ if (!unknownFields_) {
+ [self setUnknownFields:context.other.unknownFields];
+ } else {
+ [unknownFields_ mergeUnknownFields:context.other.unknownFields];
+ }
+
+ if (other->extensionMap_.count == 0) {
+ return;
+ }
+
+ if (extensionMap_ == nil) {
+ extensionMap_ =
+ CloneExtensionMap(other->extensionMap_, NSZoneFromPointer(self));
+ } else {
+ for (GPBExtensionField *thisField in other->extensionMap_) {
+ id otherValue = [other->extensionMap_ objectForKey:thisField];
+ id value = [extensionMap_ objectForKey:thisField];
+ GPBExtensionDescriptor *thisFieldDescriptor = thisField.descriptor;
+ BOOL isMessageExtension = GPBExtensionIsMessage(thisFieldDescriptor);
+
+ if ([thisField isRepeated]) {
+ NSMutableArray *list = value;
+ if (list == nil) {
+ list = [[NSMutableArray alloc] init];
+ [extensionMap_ setObject:list forKey:thisField];
+ [list release];
+ }
+ if (isMessageExtension) {
+ for (GPBMessage *otherListValue in otherValue) {
+ GPBMessage *copiedValue = [otherListValue copy];
+ [list addObject:copiedValue];
+ [copiedValue release];
+ }
+ } else {
+ [list addObjectsFromArray:otherValue];
+ }
+ } else {
+ if (isMessageExtension) {
+ if (value) {
+ [(GPBMessage *)value mergeFrom:(GPBMessage *)otherValue];
+ } else {
+ GPBMessage *copiedValue = [otherValue copy];
+ [extensionMap_ setObject:copiedValue forKey:thisField];
+ [copiedValue release];
+ }
+ } else {
+ [extensionMap_ setObject:otherValue forKey:thisField];
+ }
+ }
+
+ if (isMessageExtension && !thisFieldDescriptor.isRepeated) {
+ GPBMessage *autocreatedValue =
+ [[autocreatedExtensionMap_ objectForKey:thisField] retain];
+ // Must remove from the map before calling GPBClearMessageAutocreator()
+ // so that GPBClearMessageAutocreator() knows its safe to clear.
+ [autocreatedExtensionMap_ removeObjectForKey:thisField];
+ GPBClearMessageAutocreator(autocreatedValue);
+ [autocreatedValue release];
+ }
+ }
+ }
+}
+
+#pragma mark - IsEqual Support
+
+typedef struct IsEqualContext {
+ GPBMessage *other;
+ GPBMessage *self;
+ BOOL outIsEqual;
+} IsEqualContext;
+
+// If both self and other "has" a value then compare.
+//%PDDM-DEFINE IS_EQUAL_FUNC(NAME, TYPE)
+//%static BOOL IsEqual##NAME(GPBFieldDescriptor *field, void *voidContext) {
+//% IsEqualContext *context = (IsEqualContext *)voidContext;
+//% int32_t hasIndex = GPBFieldHasIndex(field);
+//% uint32_t fieldNum = GPBFieldNumber(field);
+//% BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
+//% BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
+//% if (selfHas != otherHas) {
+//% context->outIsEqual = NO;
+//% return NO;
+//% }
+//% if (!selfHas) {
+//% return YES;
+//% }
+//% TYPE selfVal = GPBGet##NAME##IvarWithField(context->self, field);
+//% TYPE otherVal = GPBGet##NAME##IvarWithField(context->other, field);
+//% if (selfVal != otherVal) {
+//% context->outIsEqual = NO;
+//% return NO;
+//% }
+//% return YES;
+//%}
+//%
+//%PDDM-EXPAND IS_EQUAL_FUNC(Bool, BOOL)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IsEqualBool(GPBFieldDescriptor *field, void *voidContext) {
+ IsEqualContext *context = (IsEqualContext *)voidContext;
+ int32_t hasIndex = GPBFieldHasIndex(field);
+ uint32_t fieldNum = GPBFieldNumber(field);
+ BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
+ BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
+ if (selfHas != otherHas) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ if (!selfHas) {
+ return YES;
+ }
+ BOOL selfVal = GPBGetBoolIvarWithField(context->self, field);
+ BOOL otherVal = GPBGetBoolIvarWithField(context->other, field);
+ if (selfVal != otherVal) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND IS_EQUAL_FUNC(Int32, int32_t)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IsEqualInt32(GPBFieldDescriptor *field, void *voidContext) {
+ IsEqualContext *context = (IsEqualContext *)voidContext;
+ int32_t hasIndex = GPBFieldHasIndex(field);
+ uint32_t fieldNum = GPBFieldNumber(field);
+ BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
+ BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
+ if (selfHas != otherHas) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ if (!selfHas) {
+ return YES;
+ }
+ int32_t selfVal = GPBGetInt32IvarWithField(context->self, field);
+ int32_t otherVal = GPBGetInt32IvarWithField(context->other, field);
+ if (selfVal != otherVal) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND IS_EQUAL_FUNC(UInt32, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IsEqualUInt32(GPBFieldDescriptor *field, void *voidContext) {
+ IsEqualContext *context = (IsEqualContext *)voidContext;
+ int32_t hasIndex = GPBFieldHasIndex(field);
+ uint32_t fieldNum = GPBFieldNumber(field);
+ BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
+ BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
+ if (selfHas != otherHas) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ if (!selfHas) {
+ return YES;
+ }
+ uint32_t selfVal = GPBGetUInt32IvarWithField(context->self, field);
+ uint32_t otherVal = GPBGetUInt32IvarWithField(context->other, field);
+ if (selfVal != otherVal) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND IS_EQUAL_FUNC(Int64, int64_t)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IsEqualInt64(GPBFieldDescriptor *field, void *voidContext) {
+ IsEqualContext *context = (IsEqualContext *)voidContext;
+ int32_t hasIndex = GPBFieldHasIndex(field);
+ uint32_t fieldNum = GPBFieldNumber(field);
+ BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
+ BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
+ if (selfHas != otherHas) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ if (!selfHas) {
+ return YES;
+ }
+ int64_t selfVal = GPBGetInt64IvarWithField(context->self, field);
+ int64_t otherVal = GPBGetInt64IvarWithField(context->other, field);
+ if (selfVal != otherVal) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND IS_EQUAL_FUNC(UInt64, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IsEqualUInt64(GPBFieldDescriptor *field, void *voidContext) {
+ IsEqualContext *context = (IsEqualContext *)voidContext;
+ int32_t hasIndex = GPBFieldHasIndex(field);
+ uint32_t fieldNum = GPBFieldNumber(field);
+ BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
+ BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
+ if (selfHas != otherHas) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ if (!selfHas) {
+ return YES;
+ }
+ uint64_t selfVal = GPBGetUInt64IvarWithField(context->self, field);
+ uint64_t otherVal = GPBGetUInt64IvarWithField(context->other, field);
+ if (selfVal != otherVal) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND IS_EQUAL_FUNC(Float, float)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IsEqualFloat(GPBFieldDescriptor *field, void *voidContext) {
+ IsEqualContext *context = (IsEqualContext *)voidContext;
+ int32_t hasIndex = GPBFieldHasIndex(field);
+ uint32_t fieldNum = GPBFieldNumber(field);
+ BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
+ BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
+ if (selfHas != otherHas) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ if (!selfHas) {
+ return YES;
+ }
+ float selfVal = GPBGetFloatIvarWithField(context->self, field);
+ float otherVal = GPBGetFloatIvarWithField(context->other, field);
+ if (selfVal != otherVal) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND IS_EQUAL_FUNC(Double, double)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IsEqualDouble(GPBFieldDescriptor *field, void *voidContext) {
+ IsEqualContext *context = (IsEqualContext *)voidContext;
+ int32_t hasIndex = GPBFieldHasIndex(field);
+ uint32_t fieldNum = GPBFieldNumber(field);
+ BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
+ BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
+ if (selfHas != otherHas) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ if (!selfHas) {
+ return YES;
+ }
+ double selfVal = GPBGetDoubleIvarWithField(context->self, field);
+ double otherVal = GPBGetDoubleIvarWithField(context->other, field);
+ if (selfVal != otherVal) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND-END (7 expansions)
+
+static BOOL IsEqualObject(GPBFieldDescriptor *field, void *voidContext) {
+ IsEqualContext *context = (IsEqualContext *)voidContext;
+ if (GPBFieldIsMapOrArray(field)) {
+ // In the case of a list/map, there is no _hasIvar to worry about checking.
+ // NOTE: These are NSArray/GPB*Array/NSDictionary/GPB*Dictionary, but the
+ // type doesn't really matter as the object just has to support
+ // -count/-isEqual:.
+ NSArray *resultMapOrArray =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSArray *otherMapOrArray =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->other, field);
+ context->outIsEqual =
+ (resultMapOrArray.count == 0 && otherMapOrArray.count == 0) ||
+ [resultMapOrArray isEqual:otherMapOrArray];
+ return context->outIsEqual;
+ }
+ int32_t hasIndex = GPBFieldHasIndex(field);
+ uint32_t fieldNum = GPBFieldNumber(field);
+ BOOL selfHas = GPBGetHasIvar(context->self, hasIndex, fieldNum);
+ BOOL otherHas = GPBGetHasIvar(context->other, hasIndex, fieldNum);
+ if (selfHas != otherHas) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ if (!selfHas) {
+ return YES;
+ }
+ // GPBGetObjectIvarWithFieldNoAutocreate skips the has check, faster.
+ NSObject *selfVal =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSObject *otherVal =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->other, field);
+
+ // This covers case where selfVal is set to nil, as well as shortcuts the call
+ // to isEqual: in common cases.
+ if (selfVal == otherVal) {
+ return YES;
+ }
+ if (![selfVal isEqual:otherVal]) {
+ context->outIsEqual = NO;
+ return NO;
+ }
+ return YES;
+}
+
+- (BOOL)isEqual:(GPBMessage *)other {
+ if (other == self) {
+ return YES;
+ }
+ if (![other isKindOfClass:[self class]] &&
+ ![self isKindOfClass:[other class]]) {
+ return NO;
+ }
+ GPBApplyFunctions funcs = GPBAPPLY_FUNCTIONS_INIT(IsEqual);
+ IsEqualContext context = {other, self, YES};
+ GPBApplyFunctionsToMessageFields(&funcs, self, &context);
+ if (!context.outIsEqual) {
+ return NO;
+ }
+
+ // nil and empty are equal
+ if (extensionMap_.count != 0 || other->extensionMap_.count != 0) {
+ if (![extensionMap_ isEqual:other->extensionMap_]) {
+ return NO;
+ }
+ }
+
+ // nil and empty are equal
+ GPBUnknownFieldSet *otherUnknowns = other.unknownFields;
+ if ([unknownFields_ countOfFields] != 0 ||
+ [otherUnknowns countOfFields] != 0) {
+ if (![unknownFields_ isEqual:otherUnknowns]) {
+ return NO;
+ }
+ }
+ return YES;
+}
+
+// It is very difficult to implement a generic hash for ProtoBuf messages that
+// will perform well. If you need hashing on your ProtoBufs (eg you are using
+// them as dictionary keys) you will probably want to implement a ProtoBuf
+// message specific hash as a category on your protobuf class. Do not make it a
+// category on GPBMessage as you will conflict with this hash, and will possibly
+// override hash for all generated protobufs. A good implementation of hash will
+// be really fast, so we would recommend only hashing protobufs that have an
+// identifier field of some kind that you can easily hash. If you implement
+// hash, we would strongly recommend overriding isEqual: in your category as
+// well, as the default implementation of isEqual: is extremely slow, and may
+// drastically affect performance in large sets.
+- (NSUInteger)hash {
+ GPBDescriptor *descriptor = [[self class] descriptor];
+ const NSUInteger prime = 19;
+
+ // Start with the descriptor and then mix it with the field numbers that
+ // are set. Hopefully that will give a spread based on classes and what
+ // fields are set.
+ NSUInteger result = (NSUInteger)descriptor;
+ for (GPBFieldDescriptor *field in descriptor->fields_) {
+ if (GPBFieldIsMapOrArray(field)) {
+ // Exact type doesn't matter, just check if there are any elements.
+ NSArray *mapOrArray = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (mapOrArray.count) {
+ result = prime * result + GPBFieldNumber(field);
+ }
+ } else if (GPBGetHasIvarField(self, field)) {
+ result = prime * result + GPBFieldNumber(field);
+ }
+ }
+ return result;
+}
+
+#pragma mark - Description Support
+
+- (NSString *)description {
+ NSString *textFormat = GPBTextFormatForMessage(self, @" ");
+ NSString *description = [NSString
+ stringWithFormat:@"<%@ %p>: {\n%@}", [self class], self, textFormat];
+ return description;
+}
+
+#if DEBUG
+
+// Xcode 5.1 added support for custom quick look info.
+// https://developer.apple.com/library/ios/documentation/IDEs/Conceptual/CustomClassDisplay_in_QuickLook/CH01-quick_look_for_custom_objects/CH01-quick_look_for_custom_objects.html#//apple_ref/doc/uid/TP40014001-CH2-SW1
+- (id)debugQuickLookObject {
+ return GPBTextFormatForMessage(self, nil);
+}
+
+#endif // DEBUG
+
+#pragma mark - SerializedSize Support
+
+// Serialized size is only calculated once, and then is stored into
+// memoizedSerializedSize.
+
+typedef struct SerializedSizeContext {
+ GPBMessage *self;
+ size_t outSize;
+} SerializedSizeContext;
+
+//%PDDM-DEFINE SERIALIZED_SIZE_POD_FUNC(NAME, TYPE, REAL_TYPE)
+//%SERIALIZED_SIZE_POD_FUNC_FULL(NAME, TYPE, REAL_TYPE, REAL_TYPE, )
+//%PDDM-DEFINE SERIALIZED_SIZE_POD_FUNC_FULL(NAME, TYPE, REAL_TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME)
+//%static BOOL DynamicSerializedSize##NAME(GPBFieldDescriptor *field,
+//% NAME$S void *voidContext) {
+//% SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+//% GPBFieldType fieldType = field.fieldType;
+//% if (fieldType == GPBFieldTypeRepeated) {
+//% GPB##ARRAY_TYPE##Array *array =
+//% GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+//% NSUInteger count = array.count;
+//% if (count == 0) return YES;
+//% __block size_t dataSize = 0;
+//% [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% #pragma unused(idx, stop)
+//% dataSize += GPBCompute##NAME##SizeNoTag(value);
+//% }];
+//% context->outSize += dataSize;
+//% size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+//% if (field.isPackable) {
+//% context->outSize += tagSize;
+//% context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+//% } else {
+//% context->outSize += count * tagSize;
+//% }
+//% } else if (fieldType == GPBFieldTypeSingle) {
+//% BOOL selfHas = GPBGetHasIvarField(context->self, field);
+//% if (selfHas) {
+//% TYPE selfVal = GPBGet##REAL_TYPE##IvarWithField(context->self, field);
+//% context->outSize += GPBCompute##NAME##Size(GPBFieldNumber(field), selfVal);
+//% }
+//% } else { // fieldType == GPBFieldTypeMap
+//% // Type will be GPB*##REAL_TYPE##Dictionary, exact type doesn't matter.
+//% GPBInt32##REAL_TYPE##Dictionary *map =
+//% GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+//% context->outSize += [map computeSerializedSizeAsField:field];
+//% }
+//% return YES;
+//%}
+//%
+//%PDDM-DEFINE SERIALIZED_SIZE_OBJECT_FUNC(NAME)
+//%static BOOL DynamicSerializedSize##NAME(GPBFieldDescriptor *field,
+//% NAME$S void *voidContext) {
+//% SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+//% GPBFieldType fieldType = field.fieldType;
+//% if (fieldType == GPBFieldTypeRepeated) {
+//% NSArray *array =
+//% GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+//% for (id value in array) {
+//% context->outSize += GPBCompute##NAME##SizeNoTag(value);
+//% }
+//% size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field),
+//% GPBGetFieldType(field));
+//% context->outSize += array.count * tagSize;
+//% } else if (fieldType == GPBFieldTypeSingle) {
+//% BOOL selfHas = GPBGetHasIvarField(context->self, field);
+//% if (selfHas) {
+//% // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+//% // again.
+//% id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+//% context->outSize += GPBCompute##NAME##Size(GPBFieldNumber(field), selfVal);
+//% }
+//% } else { // fieldType == GPBFieldTypeMap
+//% GPBType mapKeyType = field.mapKeyType;
+//% if (mapKeyType == GPBTypeString) {
+//% // If key type was string, then the map is an NSDictionary.
+//% NSDictionary *map =
+//% GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+//% context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field);
+//% } else {
+//% // Type will be GPB*##NAME##Dictionary, exact type doesn't matter.
+//% GPBInt32ObjectDictionary *map =
+//% GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+//% context->outSize += [map computeSerializedSizeAsField:field];
+//% }
+//% }
+//% return YES;
+//%}
+//%
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Bool, BOOL, Bool)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeBool(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBBoolArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeBoolSizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ BOOL selfVal = GPBGetBoolIvarWithField(context->self, field);
+ context->outSize += GPBComputeBoolSize(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*BoolDictionary, exact type doesn't matter.
+ GPBInt32BoolDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Int32, int32_t, Int32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeInt32(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt32Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeInt32SizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ int32_t selfVal = GPBGetInt32IvarWithField(context->self, field);
+ context->outSize += GPBComputeInt32Size(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*Int32Dictionary, exact type doesn't matter.
+ GPBInt32Int32Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SInt32, int32_t, Int32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeSInt32(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt32Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeSInt32SizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ int32_t selfVal = GPBGetInt32IvarWithField(context->self, field);
+ context->outSize += GPBComputeSInt32Size(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*Int32Dictionary, exact type doesn't matter.
+ GPBInt32Int32Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SFixed32, int32_t, Int32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeSFixed32(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt32Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeSFixed32SizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ int32_t selfVal = GPBGetInt32IvarWithField(context->self, field);
+ context->outSize += GPBComputeSFixed32Size(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*Int32Dictionary, exact type doesn't matter.
+ GPBInt32Int32Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC_FULL(Enum, int32_t, Int32, Enum, Raw)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeEnum(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBEnumArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeEnumSizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ int32_t selfVal = GPBGetInt32IvarWithField(context->self, field);
+ context->outSize += GPBComputeEnumSize(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*Int32Dictionary, exact type doesn't matter.
+ GPBInt32Int32Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(UInt32, uint32_t, UInt32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeUInt32(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBUInt32Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeUInt32SizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ uint32_t selfVal = GPBGetUInt32IvarWithField(context->self, field);
+ context->outSize += GPBComputeUInt32Size(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*UInt32Dictionary, exact type doesn't matter.
+ GPBInt32UInt32Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Fixed32, uint32_t, UInt32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeFixed32(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBUInt32Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeFixed32SizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ uint32_t selfVal = GPBGetUInt32IvarWithField(context->self, field);
+ context->outSize += GPBComputeFixed32Size(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*UInt32Dictionary, exact type doesn't matter.
+ GPBInt32UInt32Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Int64, int64_t, Int64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeInt64(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt64Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeInt64SizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ int64_t selfVal = GPBGetInt64IvarWithField(context->self, field);
+ context->outSize += GPBComputeInt64Size(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*Int64Dictionary, exact type doesn't matter.
+ GPBInt32Int64Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SFixed64, int64_t, Int64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeSFixed64(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt64Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeSFixed64SizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ int64_t selfVal = GPBGetInt64IvarWithField(context->self, field);
+ context->outSize += GPBComputeSFixed64Size(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*Int64Dictionary, exact type doesn't matter.
+ GPBInt32Int64Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(SInt64, int64_t, Int64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeSInt64(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBInt64Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeSInt64SizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ int64_t selfVal = GPBGetInt64IvarWithField(context->self, field);
+ context->outSize += GPBComputeSInt64Size(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*Int64Dictionary, exact type doesn't matter.
+ GPBInt32Int64Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(UInt64, uint64_t, UInt64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeUInt64(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBUInt64Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeUInt64SizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ uint64_t selfVal = GPBGetUInt64IvarWithField(context->self, field);
+ context->outSize += GPBComputeUInt64Size(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*UInt64Dictionary, exact type doesn't matter.
+ GPBInt32UInt64Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Fixed64, uint64_t, UInt64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeFixed64(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBUInt64Array *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeFixed64SizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ uint64_t selfVal = GPBGetUInt64IvarWithField(context->self, field);
+ context->outSize += GPBComputeFixed64Size(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*UInt64Dictionary, exact type doesn't matter.
+ GPBInt32UInt64Dictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Float, float, Float)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeFloat(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBFloatArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeFloatSizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ float selfVal = GPBGetFloatIvarWithField(context->self, field);
+ context->outSize += GPBComputeFloatSize(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*FloatDictionary, exact type doesn't matter.
+ GPBInt32FloatDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_POD_FUNC(Double, double, Double)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeDouble(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ GPBDoubleArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ NSUInteger count = array.count;
+ if (count == 0) return YES;
+ __block size_t dataSize = 0;
+ [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(idx, stop)
+ dataSize += GPBComputeDoubleSizeNoTag(value);
+ }];
+ context->outSize += dataSize;
+ size_t tagSize = GPBComputeTagSize(GPBFieldNumber(field));
+ if (field.isPackable) {
+ context->outSize += tagSize;
+ context->outSize += GPBComputeSizeTSizeAsInt32NoTag(dataSize);
+ } else {
+ context->outSize += count * tagSize;
+ }
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ double selfVal = GPBGetDoubleIvarWithField(context->self, field);
+ context->outSize += GPBComputeDoubleSize(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ // Type will be GPB*DoubleDictionary, exact type doesn't matter.
+ GPBInt32DoubleDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(String)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeString(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ NSArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ for (id value in array) {
+ context->outSize += GPBComputeStringSizeNoTag(value);
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field),
+ GPBGetFieldType(field));
+ context->outSize += array.count * tagSize;
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+ // again.
+ id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += GPBComputeStringSize(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ GPBType mapKeyType = field.mapKeyType;
+ if (mapKeyType == GPBTypeString) {
+ // If key type was string, then the map is an NSDictionary.
+ NSDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field);
+ } else {
+ // Type will be GPB*StringDictionary, exact type doesn't matter.
+ GPBInt32ObjectDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Data)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeData(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ NSArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ for (id value in array) {
+ context->outSize += GPBComputeDataSizeNoTag(value);
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field),
+ GPBGetFieldType(field));
+ context->outSize += array.count * tagSize;
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+ // again.
+ id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += GPBComputeDataSize(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ GPBType mapKeyType = field.mapKeyType;
+ if (mapKeyType == GPBTypeString) {
+ // If key type was string, then the map is an NSDictionary.
+ NSDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field);
+ } else {
+ // Type will be GPB*DataDictionary, exact type doesn't matter.
+ GPBInt32ObjectDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Message)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeMessage(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ NSArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ for (id value in array) {
+ context->outSize += GPBComputeMessageSizeNoTag(value);
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field),
+ GPBGetFieldType(field));
+ context->outSize += array.count * tagSize;
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+ // again.
+ id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += GPBComputeMessageSize(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ GPBType mapKeyType = field.mapKeyType;
+ if (mapKeyType == GPBTypeString) {
+ // If key type was string, then the map is an NSDictionary.
+ NSDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field);
+ } else {
+ // Type will be GPB*MessageDictionary, exact type doesn't matter.
+ GPBInt32ObjectDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND SERIALIZED_SIZE_OBJECT_FUNC(Group)
+// This block of code is generated, do not edit it directly.
+
+static BOOL DynamicSerializedSizeGroup(GPBFieldDescriptor *field,
+ void *voidContext) {
+ SerializedSizeContext *context = (SerializedSizeContext *)voidContext;
+ GPBFieldType fieldType = field.fieldType;
+ if (fieldType == GPBFieldTypeRepeated) {
+ NSArray *array =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ for (id value in array) {
+ context->outSize += GPBComputeGroupSizeNoTag(value);
+ }
+ size_t tagSize = GPBComputeWireFormatTagSize(GPBFieldNumber(field),
+ GPBGetFieldType(field));
+ context->outSize += array.count * tagSize;
+ } else if (fieldType == GPBFieldTypeSingle) {
+ BOOL selfHas = GPBGetHasIvarField(context->self, field);
+ if (selfHas) {
+ // GPBGetObjectIvarWithFieldNoAutocreate() avoids doing the has check
+ // again.
+ id selfVal = GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += GPBComputeGroupSize(GPBFieldNumber(field), selfVal);
+ }
+ } else { // fieldType == GPBFieldTypeMap
+ GPBType mapKeyType = field.mapKeyType;
+ if (mapKeyType == GPBTypeString) {
+ // If key type was string, then the map is an NSDictionary.
+ NSDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += GPBDictionaryComputeSizeInternalHelper(map, field);
+ } else {
+ // Type will be GPB*GroupDictionary, exact type doesn't matter.
+ GPBInt32ObjectDictionary *map =
+ GPBGetObjectIvarWithFieldNoAutocreate(context->self, field);
+ context->outSize += [map computeSerializedSizeAsField:field];
+ }
+ }
+ return YES;
+}
+
+//%PDDM-EXPAND-END (18 expansions)
+
+- (size_t)serializedSize {
+ // Fields.
+ SerializedSizeContext context = {self, 0};
+ GPBApplyStrictFunctions funcs =
+ GPBAPPLY_STRICT_FUNCTIONS_INIT(DynamicSerializedSize);
+ GPBApplyStrictFunctionsToMessageFields(&funcs, self, &context);
+ // Add any unknown fields.
+ const GPBDescriptor *descriptor = [self descriptor];
+ if (descriptor.wireFormat) {
+ context.outSize += [unknownFields_ serializedSizeAsMessageSet];
+ } else {
+ context.outSize += [unknownFields_ serializedSize];
+ }
+ // Add any extensions.
+ for (GPBExtensionField *extension in extensionMap_) {
+ id value = [extensionMap_ objectForKey:extension];
+ context.outSize += [extension computeSerializedSizeIncludingTag:value];
+ }
+
+ return context.outSize;
+}
+
+#pragma mark - Resolve Methods Support
+
+typedef struct IvarAccessorMethodContext {
+ GPBFileSyntax syntax;
+ IMP impToAdd;
+ SEL encodingSelector;
+} IvarAccessorMethodContext;
+
+//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_COMMON(NAME, TYPE, TRUE_NAME)
+//%static BOOL IvarGet##NAME(GPBFieldDescriptor *field, void *voidContext) {
+//% IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+//% context->impToAdd = imp_implementationWithBlock(^(id obj) {
+//% return GPBGet##TRUE_NAME##IvarWithField(obj, field);
+//% });
+//% context->encodingSelector = @selector(get##NAME);
+//% return NO;
+//%}
+//%
+//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_OBJECT(NAME, TYPE)
+//%IVAR_ACCESSOR_FUNC_COMMON(NAME, TYPE, Object)
+//%static BOOL IvarSet##NAME(GPBFieldDescriptor *field, void *voidContext) {
+//% IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+//% // Local for syntax so the block doesn't capture context and use random
+//% // memory in the future.
+//% const GPBFileSyntax syntax = context->syntax;
+//% context->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) {
+//% return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
+//% });
+//% context->encodingSelector = @selector(set##NAME:);
+//% return NO;
+//%}
+//%
+//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_PER_VERSION(NAME, TYPE)
+//%IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(NAME, TYPE, NAME)
+//%PDDM-DEFINE IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(NAME, TYPE, TRUE_NAME)
+//%IVAR_ACCESSOR_FUNC_COMMON(NAME, TYPE, TRUE_NAME)
+//%static BOOL IvarSet##NAME(GPBFieldDescriptor *field, void *voidContext) {
+//% IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+//% // Local for syntax so the block doesn't capture context and use random
+//% // memory in the future.
+//% const GPBFileSyntax syntax = context->syntax;
+//% context->impToAdd = imp_implementationWithBlock(^(id obj, TYPE value) {
+//% return GPBSet##TRUE_NAME##IvarWithFieldInternal(obj, field, value, syntax);
+//% });
+//% context->encodingSelector = @selector(set##NAME:);
+//% return NO;
+//%}
+//%
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Bool, BOOL)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetBool(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetBoolIvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getBool);
+ return NO;
+}
+
+static BOOL IvarSetBool(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) {
+ return GPBSetBoolIvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setBool:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Int32, int32_t)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetInt32(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetInt32IvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getInt32);
+ return NO;
+}
+
+static BOOL IvarSetInt32(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) {
+ return GPBSetInt32IvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setInt32:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SInt32, int32_t, Int32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetSInt32(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetInt32IvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getSInt32);
+ return NO;
+}
+
+static BOOL IvarSetSInt32(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) {
+ return GPBSetInt32IvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setSInt32:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SFixed32, int32_t, Int32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetSFixed32(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetInt32IvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getSFixed32);
+ return NO;
+}
+
+static BOOL IvarSetSFixed32(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) {
+ return GPBSetInt32IvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setSFixed32:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(UInt32, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetUInt32(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetUInt32IvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getUInt32);
+ return NO;
+}
+
+static BOOL IvarSetUInt32(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, uint32_t value) {
+ return GPBSetUInt32IvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setUInt32:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(Fixed32, uint32_t, UInt32)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetFixed32(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetUInt32IvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getFixed32);
+ return NO;
+}
+
+static BOOL IvarSetFixed32(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, uint32_t value) {
+ return GPBSetUInt32IvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setFixed32:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Int64, int64_t)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetInt64(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetInt64IvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getInt64);
+ return NO;
+}
+
+static BOOL IvarSetInt64(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, int64_t value) {
+ return GPBSetInt64IvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setInt64:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SFixed64, int64_t, Int64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetSFixed64(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetInt64IvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getSFixed64);
+ return NO;
+}
+
+static BOOL IvarSetSFixed64(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, int64_t value) {
+ return GPBSetInt64IvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setSFixed64:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(SInt64, int64_t, Int64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetSInt64(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetInt64IvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getSInt64);
+ return NO;
+}
+
+static BOOL IvarSetSInt64(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, int64_t value) {
+ return GPBSetInt64IvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setSInt64:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(UInt64, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetUInt64(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetUInt64IvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getUInt64);
+ return NO;
+}
+
+static BOOL IvarSetUInt64(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, uint64_t value) {
+ return GPBSetUInt64IvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setUInt64:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION_ALIASED(Fixed64, uint64_t, UInt64)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetFixed64(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetUInt64IvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getFixed64);
+ return NO;
+}
+
+static BOOL IvarSetFixed64(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, uint64_t value) {
+ return GPBSetUInt64IvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setFixed64:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Float, float)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetFloat(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetFloatIvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getFloat);
+ return NO;
+}
+
+static BOOL IvarSetFloat(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, float value) {
+ return GPBSetFloatIvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setFloat:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_PER_VERSION(Double, double)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetDouble(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetDoubleIvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getDouble);
+ return NO;
+}
+
+static BOOL IvarSetDouble(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, double value) {
+ return GPBSetDoubleIvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setDouble:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(String, id)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetString(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetObjectIvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getString);
+ return NO;
+}
+
+static BOOL IvarSetString(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, id value) {
+ return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setString:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(Data, id)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetData(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetObjectIvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getData);
+ return NO;
+}
+
+static BOOL IvarSetData(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, id value) {
+ return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setData:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(Message, id)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetMessage(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetObjectIvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getMessage);
+ return NO;
+}
+
+static BOOL IvarSetMessage(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, id value) {
+ return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setMessage:);
+ return NO;
+}
+
+//%PDDM-EXPAND IVAR_ACCESSOR_FUNC_OBJECT(Group, id)
+// This block of code is generated, do not edit it directly.
+
+static BOOL IvarGetGroup(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetObjectIvarWithField(obj, field);
+ });
+ context->encodingSelector = @selector(getGroup);
+ return NO;
+}
+
+static BOOL IvarSetGroup(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, id value) {
+ return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setGroup:);
+ return NO;
+}
+
+//%PDDM-EXPAND-END (17 expansions)
+
+// Enum gets custom hooks because get needs the syntax to Get.
+
+static BOOL IvarGetEnum(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetEnumIvarWithFieldInternal(obj, field, syntax);
+ });
+ context->encodingSelector = @selector(getEnum);
+ return NO;
+}
+
+static BOOL IvarSetEnum(GPBFieldDescriptor *field, void *voidContext) {
+ IvarAccessorMethodContext *context = (IvarAccessorMethodContext *)voidContext;
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context->syntax;
+ context->impToAdd = imp_implementationWithBlock(^(id obj, int32_t value) {
+ return GPBSetEnumIvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context->encodingSelector = @selector(setEnum:);
+ return NO;
+}
+
++ (BOOL)resolveInstanceMethod:(SEL)sel {
+ const GPBDescriptor *descriptor = [self descriptor];
+ if (!descriptor) {
+ return NO;
+ }
+
+ // NOTE: hasSel_/setHasSel_ will be NULL if the field for the given message
+ // should not have has support (done in GPBDescriptor.m), so there is no need
+ // for checks here to see if has*/setHas* are allowed.
+
+ IvarAccessorMethodContext context = {descriptor.file.syntax, NULL, NULL};
+ for (GPBFieldDescriptor *field in descriptor->fields_) {
+ BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
+ if (!isMapOrArray) {
+ if (sel == field->getSel_) {
+ static const GPBApplyStrictFunctions funcs =
+ GPBAPPLY_STRICT_FUNCTIONS_INIT(IvarGet);
+ funcs[GPBGetFieldType(field)](field, &context);
+ break;
+ } else if (sel == field->hasSel_) {
+ int32_t index = GPBFieldHasIndex(field);
+ uint32_t fieldNum = GPBFieldNumber(field);
+ context.impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetHasIvar(obj, index, fieldNum);
+ });
+ context.encodingSelector = @selector(getBool);
+ break;
+ } else if (sel == field->setHasSel_) {
+ context.impToAdd = imp_implementationWithBlock(^(id obj, BOOL value) {
+ if (value) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"has fields can only be set to NO"];
+ }
+ GPBClearMessageField(obj, field);
+ });
+ context.encodingSelector = @selector(setBool:);
+ break;
+ } else if (sel == field->setSel_) {
+ GPBApplyStrictFunctions funcs = GPBAPPLY_STRICT_FUNCTIONS_INIT(IvarSet);
+ funcs[GPBGetFieldType(field)](field, &context);
+ break;
+ } else {
+ GPBOneofDescriptor *oneof = field->containingOneof_;
+ if (oneof && (sel == oneof->caseSel_)) {
+ int32_t index = oneof->oneofDescription_->index;
+ context.impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GPBGetHasOneof(obj, index);
+ });
+ context.encodingSelector = @selector(getEnum);
+ break;
+ }
+ }
+ } else {
+ if (sel == field->getSel_) {
+ context.impToAdd = imp_implementationWithBlock(^(id obj) {
+ return GetArrayIvarWithField(obj, field);
+ });
+ context.encodingSelector = @selector(getArray);
+ break;
+ } else if (sel == field->setSel_) {
+ // Local for syntax so the block doesn't capture context and use random
+ // memory in the future.
+ const GPBFileSyntax syntax = context.syntax;
+ context.impToAdd = imp_implementationWithBlock(^(id obj, id value) {
+ return GPBSetObjectIvarWithFieldInternal(obj, field, value, syntax);
+ });
+ context.encodingSelector = @selector(setArray:);
+ break;
+ }
+ }
+ }
+ if (context.impToAdd) {
+ const char *encoding =
+ GPBMessageEncodingForSelector(context.encodingSelector, YES);
+ BOOL methodAdded = class_addMethod(descriptor.messageClass, sel,
+ context.impToAdd, encoding);
+ return methodAdded;
+ }
+ return [super resolveInstanceMethod:sel];
+}
+
+#pragma mark - NSCoding Support
+
+- (instancetype)initWithCoder:(NSCoder *)aDecoder {
+ self = [self init];
+ if (self) {
+ [self mergeFromData:[aDecoder decodeDataObject] extensionRegistry:nil];
+ }
+ return self;
+}
+
+- (void)encodeWithCoder:(NSCoder *)aCoder {
+ [aCoder encodeDataObject:[self data]];
+}
+
+#pragma mark - KVC Support
+
++ (BOOL)accessInstanceVariablesDirectly {
+ // Make sure KVC doesn't use instance variables.
+ return NO;
+}
+
+@end
diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h
new file mode 100644
index 00000000..f2a3d5fa
--- /dev/null
+++ b/objectivec/GPBMessage_PackagePrivate.h
@@ -0,0 +1,124 @@
+// 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.
+
+// This header is private to the ProtobolBuffers library and must NOT be
+// included by any sources outside this library. The contents of this file are
+// subject to change at any time without notice.
+
+#import "GPBMessage.h"
+
+#import <libkern/OSAtomic.h>
+
+#import "GPBBootstrap.h"
+
+typedef struct GPBMessage_Storage {
+ uint32_t _has_storage_[0];
+} GPBMessage_Storage;
+
+typedef struct GPBMessage_Storage *GPBMessage_StoragePtr;
+
+@interface GPBMessage () {
+ @package
+ // NOTE: Because of the +allocWithZone code using NSAllocateObject(),
+ // this structure should ideally always be kept pointer aligned where the
+ // real storage starts is also pointer aligned. The compiler/runtime already
+ // do this, but it may not be documented.
+
+ // A pointer to the actual fields of the subclasses. The actual structure
+ // pointed to by this pointer will depend on the subclass.
+ // All of the actual structures will start the same as
+ // GPBMessage_Storage with _has_storage__ as the first field.
+ // Kept public because static functions need to access it.
+ GPBMessage_StoragePtr messageStorage_;
+
+ // A lock to provide mutual exclusion from internal data that can be modified
+ // 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_;
+}
+
+// Gets an extension value without autocreating the result if not found. (i.e.
+// returns nil if the extension is not set)
+- (id)getExistingExtension:(GPBExtensionField *)extension;
+
+// Returns an array of GPBExtensionField* for all the extensions currently
+// in use on the message. They are sorted by field number.
+- (NSArray *)sortedExtensionsInUse;
+
+// Parses a message of this type from the input and merges it with this
+// message.
+//
+// Warning: This does not verify that all required fields are present in
+// the input message.
+// Note: The caller should call
+// -[CodedInputStream checkLastTagWas:] after calling this to
+// verify that the last tag seen was the appropriate end-group tag,
+// or zero for EOF.
+- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:(GPBExtensionRegistry *)extensionRegistry;
+
+// Parses the next delimited message of this type from the input and merges it
+// with this message.
+- (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
+ extensionRegistry:
+ (GPBExtensionRegistry *)extensionRegistry;
+
+- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data;
+
+@end
+
+CF_EXTERN_C_BEGIN
+
+// Returns a new instance that was automatically created by |autocreator| for
+// its field |field|.
+GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass,
+ GPBMessage *autocreator,
+ GPBFieldDescriptor *field)
+ __attribute__((ns_returns_retained));
+
+// Returns whether |message| autocreated this message. This is NO if the message
+// was not autocreated by |message| or if it has been mutated since
+// autocreation.
+BOOL GPBWasMessageAutocreatedBy(GPBMessage *message, GPBMessage *parent);
+
+// Call this when you mutate a message. It will cause the message to become
+// visible to its autocreator.
+void GPBBecomeVisibleToAutocreator(GPBMessage *self);
+
+// Call this when an array is mutabled so the parent message that autocreated
+// it can react.
+void GPBAutocreatedArrayModified(GPBMessage *self, id array);
+
+// Clear the autocreator, if any. Asserts if the autocreator still has an
+// autocreated reference to this message.
+void GPBClearMessageAutocreator(GPBMessage *self);
+
+CF_EXTERN_C_END
diff --git a/objectivec/GPBProtocolBuffers.h b/objectivec/GPBProtocolBuffers.h
new file mode 100644
index 00000000..436c9836
--- /dev/null
+++ b/objectivec/GPBProtocolBuffers.h
@@ -0,0 +1,45 @@
+// 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 "GPBBootstrap.h"
+
+#import "GPBArray.h"
+#import "GPBCodedInputStream.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBDescriptor.h"
+#import "GPBDictionary.h"
+#import "GPBExtensionField.h"
+#import "GPBExtensionRegistry.h"
+#import "GPBField.h"
+#import "GPBMessage.h"
+#import "GPBRootObject.h"
+#import "GPBUnknownFieldSet.h"
+#import "GPBUtilities.h"
+#import "GPBWireFormat.h"
diff --git a/objectivec/GPBProtocolBuffers.m b/objectivec/GPBProtocolBuffers.m
new file mode 100644
index 00000000..96eeb1d3
--- /dev/null
+++ b/objectivec/GPBProtocolBuffers.m
@@ -0,0 +1,49 @@
+// 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.
+
+// If you want to build protocol buffers in your own project without adding the
+// project dependency, you can just add this file.
+
+#import "GPBArray.m"
+#import "GPBCodedInputStream.m"
+#import "GPBCodedOutputStream.m"
+#import "GPBDescriptor.m"
+#import "GPBDictionary.m"
+#import "GPBExtensionField.m"
+#import "GPBExtensionRegistry.m"
+#import "GPBField.m"
+#import "GPBMessage.m"
+#import "GPBRootObject.m"
+#import "GPBUnknownFieldSet.m"
+#import "GPBUtilities.m"
+#import "GPBWellKnownTypes.m"
+#import "GPBWireFormat.m"
+
+#import "google/protobuf/Descriptor.pbobjc.m"
diff --git a/objectivec/GPBProtocolBuffers_RuntimeSupport.h b/objectivec/GPBProtocolBuffers_RuntimeSupport.h
new file mode 100644
index 00000000..ac3226ef
--- /dev/null
+++ b/objectivec/GPBProtocolBuffers_RuntimeSupport.h
@@ -0,0 +1,41 @@
+// 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.
+
+// This header is meant to only be used by the generated source, it should not
+// be included in code using protocol buffers.
+
+#import "GPBProtocolBuffers.h"
+
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBExtensionField_PackagePrivate.h"
+#import "GPBExtensionRegistry_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBRootObject_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
diff --git a/objectivec/GPBRootObject.h b/objectivec/GPBRootObject.h
new file mode 100644
index 00000000..2904162e
--- /dev/null
+++ b/objectivec/GPBRootObject.h
@@ -0,0 +1,42 @@
+// 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 <Foundation/Foundation.h>
+
+@class GPBExtensionRegistry;
+
+// All Root Objects derive from GPBRootObject. It supplies a registry
+// for derived classes to register their extensions to.
+@interface GPBRootObject : NSObject
+
+// Per class registry.
++ (GPBExtensionRegistry *)extensionRegistry;
+
+@end
diff --git a/objectivec/GPBRootObject.m b/objectivec/GPBRootObject.m
new file mode 100644
index 00000000..b58f95ce
--- /dev/null
+++ b/objectivec/GPBRootObject.m
@@ -0,0 +1,177 @@
+// 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 "GPBRootObject_PackagePrivate.h"
+
+#import <objc/runtime.h>
+
+#import <CoreFoundation/CoreFoundation.h>
+
+#import "GPBDescriptor.h"
+#import "GPBExtensionField.h"
+#import "GPBUtilities_PackagePrivate.h"
+
+@interface GPBExtensionDescriptor (GPBRootObject)
+// Get singletonName as a c string.
+- (const char *)singletonNameC;
+@end
+
+@implementation GPBRootObject
+
+// Taken from http://www.burtleburtle.net/bob/hash/doobs.html
+// Public Domain
+static uint32_t jenkins_one_at_a_time_hash(const char *key) {
+ uint32_t hash = 0;
+ for (uint32_t i = 0; key[i] != '\0'; ++i) {
+ hash += key[i];
+ hash += (hash << 10);
+ hash ^= (hash >> 6);
+ }
+ hash += (hash << 3);
+ hash ^= (hash >> 11);
+ hash += (hash << 15);
+ return hash;
+}
+
+// Key methods for our custom CFDictionary.
+// Note that the dictionary lasts for the lifetime of our app, so no need
+// to worry about deallocation. All of the items are added to it at
+// startup, and so the keys don't need to be retained/released.
+// Keys are NULL terminated char *.
+static const void *GPBRootExtensionKeyRetain(CFAllocatorRef allocator,
+ const void *value) {
+#pragma unused(allocator)
+ return value;
+}
+
+static void GPBRootExtensionKeyRelease(CFAllocatorRef allocator,
+ const void *value) {
+#pragma unused(allocator)
+#pragma unused(value)
+}
+
+static CFStringRef GPBRootExtensionCopyKeyDescription(const void *value) {
+ const char *key = (const char *)value;
+ return CFStringCreateWithCString(kCFAllocatorDefault, key,
+ kCFStringEncodingUTF8);
+}
+
+static Boolean GPBRootExtensionKeyEqual(const void *value1,
+ const void *value2) {
+ const char *key1 = (const char *)value1;
+ const char *key2 = (const char *)value2;
+ return strcmp(key1, key2) == 0;
+}
+
+static CFHashCode GPBRootExtensionKeyHash(const void *value) {
+ const char *key = (const char *)value;
+ return jenkins_one_at_a_time_hash(key);
+}
+
+static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL;
+
++ (void)initialize {
+ if (!gExtensionSingletonDictionary) {
+ CFDictionaryKeyCallBacks keyCallBacks = {
+ // See description above for reason for using custom dictionary.
+ 0,
+ GPBRootExtensionKeyRetain,
+ GPBRootExtensionKeyRelease,
+ GPBRootExtensionCopyKeyDescription,
+ GPBRootExtensionKeyEqual,
+ GPBRootExtensionKeyHash,
+ };
+ gExtensionSingletonDictionary =
+ CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+}
+
++ (GPBExtensionRegistry *)extensionRegistry {
+ // Is overridden in all the subclasses that provide extensions to provide the
+ // per class one.
+ return nil;
+}
+
++ (void)globallyRegisterExtension:(GPBExtensionField *)field {
+ const char *key = [field.descriptor singletonNameC];
+ // Register happens at startup, so there is no thread safety issue in
+ // modifying the dictionary.
+ CFDictionarySetValue(gExtensionSingletonDictionary, key, field);
+}
+
+static id ExtensionForName(id self, SEL _cmd) {
+ // Really fast way of doing "classname_selName".
+ // This came up as a hotspot (creation of NSString *) when accessing a
+ // lot of extensions.
+ const char *className = class_getName(self);
+ const char *selName = sel_getName(_cmd);
+ size_t classNameLen = strlen(className);
+ size_t selNameLen = strlen(selName);
+ char key[classNameLen + selNameLen + 2];
+ memcpy(key, className, classNameLen);
+ key[classNameLen] = '_';
+ memcpy(&key[classNameLen + 1], selName, selNameLen);
+ key[classNameLen + 1 + selNameLen] = '\0';
+ id extension = (id)CFDictionaryGetValue(gExtensionSingletonDictionary, key);
+ // We can't remove the key from the dictionary here (as an optimization),
+ // because resolveClassMethod can happen on any thread and we'd then need
+ // a lock.
+ return extension;
+}
+
++ (BOOL)resolveClassMethod:(SEL)sel {
+ // Another option would be to register the extensions with the class at
+ // globallyRegisterExtension:
+ // Timing the two solutions, this solution turned out to be much faster
+ // and reduced startup time, and runtime memory.
+ // On an iPhone 5s:
+ // ResolveClassMethod: 1515583 nanos
+ // globallyRegisterExtension: 2453083 nanos
+ // The advantage to globallyRegisterExtension is that it would reduce the
+ // size of the protos somewhat because the singletonNameC wouldn't need
+ // to include the class name. For a class with a lot of extensions it
+ // can add up. You could also significantly reduce the code complexity of this
+ // file.
+ id extension = ExtensionForName(self, sel);
+ if (extension != nil) {
+ const char *encoding =
+ GPBMessageEncodingForSelector(@selector(getClassValue), NO);
+ Class metaClass = objc_getMetaClass(class_getName(self));
+ IMP imp = imp_implementationWithBlock(^(id obj) {
+#pragma unused(obj)
+ return extension;
+ });
+ return class_addMethod(metaClass, sel, imp, encoding);
+ }
+ return [super resolveClassMethod:sel];
+}
+
+@end
diff --git a/objectivec/GPBRootObject_PackagePrivate.h b/objectivec/GPBRootObject_PackagePrivate.h
new file mode 100644
index 00000000..4e1d3913
--- /dev/null
+++ b/objectivec/GPBRootObject_PackagePrivate.h
@@ -0,0 +1,42 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBRootObject.h"
+
+@class GPBExtensionField;
+
+@interface GPBRootObject ()
+
+// Globally register.
++ (void)globallyRegisterExtension:(GPBExtensionField *)field;
+
+@end
diff --git a/objectivec/GPBTypes.h b/objectivec/GPBTypes.h
new file mode 100644
index 00000000..49c2b9e4
--- /dev/null
+++ b/objectivec/GPBTypes.h
@@ -0,0 +1,102 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBBootstrap.h"
+
+@class GPBEnumDescriptor;
+@class GPBMessage;
+@class GPBInt32Array;
+
+// Function used to verify that a given value can be represented by an
+// enum type.
+typedef BOOL (*GPBEnumValidationFunc)(int32_t);
+
+// Function used to fetch an EnumDescriptor.
+typedef GPBEnumDescriptor *(*GPBEnumDescriptorFunc)(void);
+
+// Magic values used for when an the at runtime to indicate an enum value
+// that wasn't know at compile time.
+enum {
+ kGPBUnrecognizedEnumeratorValue = (int32_t)0xFBADBEEF,
+};
+
+// A union for storing all possible Protobuf values.
+// Note that owner is responsible for memory management of object types.
+typedef union {
+ BOOL valueBool;
+ int32_t valueInt32;
+ int64_t valueInt64;
+ uint32_t valueUInt32;
+ uint64_t valueUInt64;
+ float valueFloat;
+ double valueDouble;
+ GPB_UNSAFE_UNRETAINED NSData *valueData;
+ GPB_UNSAFE_UNRETAINED NSString *valueString;
+ GPB_UNSAFE_UNRETAINED GPBMessage *valueMessage;
+ int32_t valueEnum;
+} GPBValue;
+
+// Do not change the order of this enum (or add things to it) without thinking
+// about it very carefully. There are several things that depend on the order.
+typedef enum {
+ GPBTypeBool = 0,
+ GPBTypeFixed32,
+ GPBTypeSFixed32,
+ GPBTypeFloat,
+ GPBTypeFixed64,
+ GPBTypeSFixed64,
+ GPBTypeDouble,
+ GPBTypeInt32,
+ GPBTypeInt64,
+ GPBTypeSInt32,
+ GPBTypeSInt64,
+ GPBTypeUInt32,
+ GPBTypeUInt64,
+ GPBTypeData, // Maps to Bytes Protobuf type
+ GPBTypeString,
+ GPBTypeMessage,
+ GPBTypeGroup,
+ GPBTypeEnum,
+} GPBType;
+
+enum {
+ // A count of the number of types in GPBType. Separated out from the GPBType
+ // enum to avoid warnings regarding not handling GPBTypeCount in switch
+ // statements.
+ GPBTypeCount = GPBTypeEnum + 1
+};
+
+// An extension range.
+typedef struct GPBExtensionRange {
+ uint32_t start; // inclusive
+ uint32_t end; // exclusive
+} GPBExtensionRange;
diff --git a/objectivec/GPBUnknownFieldSet.h b/objectivec/GPBUnknownFieldSet.h
new file mode 100644
index 00000000..48824f10
--- /dev/null
+++ b/objectivec/GPBUnknownFieldSet.h
@@ -0,0 +1,46 @@
+// 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 <Foundation/Foundation.h>
+
+@class GPBField;
+
+@interface GPBUnknownFieldSet : NSObject<NSCopying>
+
+- (BOOL)hasField:(int32_t)number;
+- (GPBField *)getField:(int32_t)number;
+- (NSUInteger)countOfFields;
+
+- (void)addField:(GPBField *)field;
+
+// Returns an NSArray of the GPBFields sorted by the field numbers.
+- (NSArray *)sortedFields;
+
+@end
diff --git a/objectivec/GPBUnknownFieldSet.m b/objectivec/GPBUnknownFieldSet.m
new file mode 100644
index 00000000..d7154dc8
--- /dev/null
+++ b/objectivec/GPBUnknownFieldSet.m
@@ -0,0 +1,422 @@
+// 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 "GPBUnknownFieldSet_PackagePrivate.h"
+
+#import "GPBCodedInputStream_PackagePrivate.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBField_PackagePrivate.h"
+#import "GPBUtilities.h"
+#import "GPBWireFormat.h"
+
+#pragma mark CFDictionaryKeyCallBacks
+
+// We use a custom dictionary here because our keys are numbers and
+// conversion back and forth from NSNumber was costing us performance.
+// If/when we move to C++ this could be done using a std::map and some
+// careful retain/release calls.
+
+static const void *GPBUnknownFieldSetKeyRetain(CFAllocatorRef allocator,
+ const void *value) {
+#pragma unused(allocator)
+ return value;
+}
+
+static void GPBUnknownFieldSetKeyRelease(CFAllocatorRef allocator,
+ const void *value) {
+#pragma unused(allocator)
+#pragma unused(value)
+}
+
+static CFStringRef GPBUnknownFieldSetCopyKeyDescription(const void *value) {
+ return CFStringCreateWithFormat(kCFAllocatorDefault, NULL, CFSTR("%d"),
+ (int)value);
+}
+
+static Boolean GPBUnknownFieldSetKeyEqual(const void *value1,
+ const void *value2) {
+ return value1 == value2;
+}
+
+static CFHashCode GPBUnknownFieldSetKeyHash(const void *value) {
+ return (CFHashCode)value;
+}
+
+#pragma mark Helpers
+
+static void checkNumber(int32_t number) {
+ if (number == 0) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"Zero is not a valid field number."];
+ }
+}
+
+@implementation GPBUnknownFieldSet {
+ @package
+ CFMutableDictionaryRef fields_;
+}
+
+static void CopyWorker(const void *key, const void *value, void *context) {
+#pragma unused(key)
+ GPBField *field = value;
+ GPBUnknownFieldSet *result = context;
+
+ GPBField *copied = [field copy];
+ [result addField:copied];
+ [copied release];
+}
+
+- (id)copyWithZone:(NSZone *)zone {
+ GPBUnknownFieldSet *result = [[GPBUnknownFieldSet allocWithZone:zone] init];
+ if (fields_) {
+ CFDictionaryApplyFunction(fields_, CopyWorker, result);
+ }
+ return result;
+}
+
+- (void)dealloc {
+ if (fields_) {
+ CFRelease(fields_);
+ }
+ [super dealloc];
+}
+
+- (BOOL)isEqual:(id)object {
+ BOOL equal = NO;
+ if ([object isKindOfClass:[GPBUnknownFieldSet class]]) {
+ GPBUnknownFieldSet *set = (GPBUnknownFieldSet *)object;
+ if ((fields_ == NULL) && (set->fields_ == NULL)) {
+ equal = YES;
+ } else if ((fields_ != NULL) && (set->fields_ != NULL)) {
+ equal = CFEqual(fields_, set->fields_);
+ }
+ }
+ return equal;
+}
+
+- (NSUInteger)hash {
+ // Return the hash of the fields dictionary (or just some value).
+ if (fields_) {
+ return CFHash(fields_);
+ }
+ return (NSUInteger)[GPBUnknownFieldSet class];
+}
+
+#pragma mark - Public Methods
+
+- (BOOL)hasField:(int32_t)number {
+ ssize_t key = number;
+ return fields_ ? (CFDictionaryGetValue(fields_, (void *)key) != nil) : NO;
+}
+
+- (GPBField *)getField:(int32_t)number {
+ ssize_t key = number;
+ GPBField *result = fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil;
+ return result;
+}
+
+- (NSUInteger)countOfFields {
+ return fields_ ? CFDictionaryGetCount(fields_) : 0;
+}
+
+- (NSArray *)sortedFields {
+ if (!fields_) return nil;
+ size_t count = CFDictionaryGetCount(fields_);
+ ssize_t keys[count];
+ GPBField *values[count];
+ CFDictionaryGetKeysAndValues(fields_, (const void **)keys,
+ (const void **)values);
+ struct GPBFieldPair {
+ ssize_t key;
+ GPBField *value;
+ } pairs[count];
+ for (size_t i = 0; i < count; ++i) {
+ pairs[i].key = keys[i];
+ pairs[i].value = values[i];
+ };
+ qsort_b(pairs, count, sizeof(struct GPBFieldPair),
+ ^(const void *first, const void *second) {
+ const struct GPBFieldPair *a = first;
+ const struct GPBFieldPair *b = second;
+ return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1);
+ });
+ for (size_t i = 0; i < count; ++i) {
+ values[i] = pairs[i].value;
+ };
+ return [NSArray arrayWithObjects:values count:count];
+}
+
+#pragma mark - Internal Methods
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output {
+ if (!fields_) return;
+ size_t count = CFDictionaryGetCount(fields_);
+ ssize_t keys[count];
+ GPBField *values[count];
+ CFDictionaryGetKeysAndValues(fields_, (const void **)keys,
+ (const void **)values);
+ if (count > 1) {
+ struct GPBFieldPair {
+ ssize_t key;
+ GPBField *value;
+ } pairs[count];
+
+ for (size_t i = 0; i < count; ++i) {
+ pairs[i].key = keys[i];
+ pairs[i].value = values[i];
+ };
+ qsort_b(pairs, count, sizeof(struct GPBFieldPair),
+ ^(const void *first, const void *second) {
+ const struct GPBFieldPair *a = first;
+ const struct GPBFieldPair *b = second;
+ return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1);
+ });
+ for (size_t i = 0; i < count; ++i) {
+ GPBField *value = pairs[i].value;
+ [value writeToOutput:output];
+ }
+ } else {
+ [values[0] writeToOutput:output];
+ }
+}
+
+- (NSString *)description {
+ NSMutableString *description = [NSMutableString
+ stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self];
+ NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @" ");
+ [description appendString:textFormat];
+ [description appendString:@"}"];
+ return description;
+}
+
+static void GPBUnknownFieldSetSerializedSize(const void *key, const void *value,
+ void *context) {
+#pragma unused(key)
+ GPBField *field = value;
+ size_t *result = context;
+ *result += [field serializedSize];
+}
+
+- (size_t)serializedSize {
+ size_t result = 0;
+ if (fields_) {
+ CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSize,
+ &result);
+ }
+ return result;
+}
+
+static void GPBUnknownFieldSetWriteAsMessageSetTo(const void *key,
+ const void *value,
+ void *context) {
+#pragma unused(key)
+ GPBField *field = value;
+ GPBCodedOutputStream *output = context;
+ [field writeAsMessageSetExtensionToOutput:output];
+}
+
+- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output {
+ if (fields_) {
+ CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetWriteAsMessageSetTo,
+ output);
+ }
+}
+
+static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key,
+ const void *value,
+ void *context) {
+#pragma unused(key)
+ GPBField *field = value;
+ size_t *result = context;
+ *result += [field serializedSizeAsMessageSetExtension];
+}
+
+- (size_t)serializedSizeAsMessageSet {
+ size_t result = 0;
+ if (fields_) {
+ CFDictionaryApplyFunction(
+ fields_, GPBUnknownFieldSetSerializedSizeAsMessageSet, &result);
+ }
+ return result;
+}
+
+- (NSData *)data {
+ NSMutableData *data = [NSMutableData dataWithLength:self.serializedSize];
+ GPBCodedOutputStream *output =
+ [[GPBCodedOutputStream alloc] initWithData:data];
+ [self writeToCodedOutputStream:output];
+ [output release];
+ return data;
+}
+
++ (BOOL)isFieldTag:(int32_t)tag {
+ return GPBWireFormatGetTagWireType(tag) != GPBWireFormatEndGroup;
+}
+
+- (void)addField:(GPBField *)field {
+ int32_t number = [field number];
+ checkNumber(number);
+ if (!fields_) {
+ CFDictionaryKeyCallBacks keyCallBacks = {
+ // See description above for reason for using custom dictionary.
+ 0, GPBUnknownFieldSetKeyRetain, GPBUnknownFieldSetKeyRelease,
+ GPBUnknownFieldSetCopyKeyDescription, GPBUnknownFieldSetKeyEqual,
+ GPBUnknownFieldSetKeyHash,
+ };
+ fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks,
+ &kCFTypeDictionaryValueCallBacks);
+ }
+ ssize_t key = number;
+ CFDictionarySetValue(fields_, (const void *)key, field);
+}
+
+- (GPBField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create {
+ ssize_t key = number;
+ GPBField *existing =
+ fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil;
+ if (!existing && create) {
+ existing = [[GPBField alloc] initWithNumber:number];
+ // This retains existing.
+ [self addField:existing];
+ [existing release];
+ }
+ return existing;
+}
+
+static void GPBUnknownFieldSetMergeUnknownFields(const void *key,
+ const void *value,
+ void *context) {
+#pragma unused(key)
+ GPBField *field = value;
+ GPBUnknownFieldSet *self = context;
+
+ int32_t number = [field number];
+ checkNumber(number);
+ GPBField *oldField = [self mutableFieldForNumber:number create:NO];
+ if (oldField) {
+ [oldField mergeFromField:field];
+ } else {
+ // Merge only comes from GPBMessage's mergeFrom:, so it means we are on
+ // mutable message and are an mutable instance, so make sure we need
+ // mutable fields.
+ GPBField *fieldCopy = [field copy];
+ [self addField:fieldCopy];
+ [fieldCopy release];
+ }
+}
+
+- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other {
+ if (other && other->fields_) {
+ CFDictionaryApplyFunction(other->fields_,
+ GPBUnknownFieldSetMergeUnknownFields, self);
+ }
+}
+
+- (void)mergeFromData:(NSData *)data {
+ GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
+ [self mergeFromCodedInputStream:input];
+ [input checkLastTagWas:0];
+ [input release];
+}
+
+- (void)mergeVarintField:(int32_t)number value:(int32_t)value {
+ checkNumber(number);
+ [[self mutableFieldForNumber:number create:YES] addVarint:value];
+}
+
+- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input {
+ int32_t number = GPBWireFormatGetTagFieldNumber(tag);
+ GPBCodedInputStreamState *state = &input->state_;
+ switch (GPBWireFormatGetTagWireType(tag)) {
+ case GPBWireFormatVarint: {
+ GPBField *field = [self mutableFieldForNumber:number create:YES];
+ [field addVarint:GPBCodedInputStreamReadInt64(state)];
+ return YES;
+ }
+ case GPBWireFormatFixed64: {
+ GPBField *field = [self mutableFieldForNumber:number create:YES];
+ [field addFixed64:GPBCodedInputStreamReadFixed64(state)];
+ return YES;
+ }
+ case GPBWireFormatLengthDelimited: {
+ NSData *data = GPBCodedInputStreamReadRetainedData(state);
+ GPBField *field = [self mutableFieldForNumber:number create:YES];
+ [field addLengthDelimited:data];
+ [data release];
+ return YES;
+ }
+ case GPBWireFormatStartGroup: {
+ GPBUnknownFieldSet *unknownFieldSet = [[GPBUnknownFieldSet alloc] init];
+ [input readUnknownGroup:number message:unknownFieldSet];
+ GPBField *field = [self mutableFieldForNumber:number create:YES];
+ [field addGroup:unknownFieldSet];
+ [unknownFieldSet release];
+ return YES;
+ }
+ case GPBWireFormatEndGroup:
+ return NO;
+ case GPBWireFormatFixed32: {
+ GPBField *field = [self mutableFieldForNumber:number create:YES];
+ [field addFixed32:GPBCodedInputStreamReadFixed32(state)];
+ return YES;
+ }
+ }
+}
+
+- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData {
+ [[self mutableFieldForNumber:number create:YES]
+ addLengthDelimited:messageData];
+}
+
+- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
+ GPBField *field = [self mutableFieldForNumber:fieldNum create:YES];
+ [field addLengthDelimited:data];
+}
+
+- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input {
+ while (YES) {
+ int32_t tag = GPBCodedInputStreamReadTag(&input->state_);
+ if (tag == 0 || ![self mergeFieldFrom:tag input:input]) {
+ break;
+ }
+ }
+}
+
+- (void)getTags:(int32_t *)tags {
+ if (!fields_) return;
+ size_t count = CFDictionaryGetCount(fields_);
+ ssize_t keys[count];
+ CFDictionaryGetKeysAndValues(fields_, (const void **)keys, NULL);
+ for (size_t i = 0; i < count; ++i) {
+ tags[i] = (int32_t)keys[i];
+ }
+}
+
+@end
diff --git a/objectivec/GPBUnknownFieldSet_PackagePrivate.h b/objectivec/GPBUnknownFieldSet_PackagePrivate.h
new file mode 100644
index 00000000..e27127ad
--- /dev/null
+++ b/objectivec/GPBUnknownFieldSet_PackagePrivate.h
@@ -0,0 +1,61 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBUnknownFieldSet.h"
+
+@class GPBCodedOutputStream;
+@class GPBCodedInputStream;
+
+@interface GPBUnknownFieldSet ()
+
++ (BOOL)isFieldTag:(int32_t)tag;
+
+- (NSData *)data;
+
+- (size_t)serializedSize;
+- (size_t)serializedSizeAsMessageSet;
+
+- (void)writeToCodedOutputStream:(GPBCodedOutputStream *)output;
+- (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output;
+
+- (void)mergeUnknownFields:(GPBUnknownFieldSet *)other;
+
+- (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input;
+- (void)mergeFromData:(NSData *)data;
+
+- (void)mergeVarintField:(int32_t)number value:(int32_t)value;
+- (BOOL)mergeFieldFrom:(int32_t)tag input:(GPBCodedInputStream *)input;
+- (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData;
+
+- (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data;
+
+@end
diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h
new file mode 100644
index 00000000..8813f1ad
--- /dev/null
+++ b/objectivec/GPBUtilities.h
@@ -0,0 +1,181 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBMessage.h"
+#import "GPBTypes.h"
+
+CF_EXTERN_C_BEGIN
+
+BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber);
+BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field);
+
+void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field);
+
+// Returns an empty NSData to assign to byte fields when you wish
+// to assign them to empty. Prevents allocating a lot of little [NSData data]
+// objects.
+NSData *GPBEmptyNSData(void) __attribute__((pure));
+
+//%PDDM-EXPAND GPB_IVAR_ACCESSORS()
+// This block of code is generated, do not edit it directly.
+
+// Getters and Setters for ivars named |name| from instance self.
+
+NSData* GPBGetDataIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetDataIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ NSData* value);
+NSString* GPBGetStringIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetStringIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ NSString* value);
+GPBMessage* GPBGetMessageIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetMessageIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ GPBMessage* value);
+GPBMessage* GPBGetGroupIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetGroupIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ GPBMessage* value);
+BOOL GPBGetBoolIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetBoolIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ BOOL value);
+int32_t GPBGetInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value);
+int32_t GPBGetSFixed32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetSFixed32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value);
+int32_t GPBGetSInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetSInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value);
+int32_t GPBGetEnumIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetEnumIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value);
+uint32_t GPBGetUInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetUInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint32_t value);
+uint32_t GPBGetFixed32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetFixed32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint32_t value);
+int64_t GPBGetInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int64_t value);
+int64_t GPBGetSInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetSInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int64_t value);
+int64_t GPBGetSFixed64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetSFixed64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int64_t value);
+uint64_t GPBGetUInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetUInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint64_t value);
+uint64_t GPBGetFixed64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetFixed64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint64_t value);
+float GPBGetFloatIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetFloatIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ float value);
+double GPBGetDoubleIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+void GPBSetDoubleIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ double value);
+//%PDDM-EXPAND-END GPB_IVAR_ACCESSORS()
+
+// Generates a sting that should be a valid "Text Format" for the C++ version
+// of Protocol Buffers. lineIndent can be nil if no additional line indent is
+// needed. The comments provide the names according to the ObjC library, they
+// most likely won't exactly match the original .proto file.
+NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent);
+NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet,
+ NSString *lineIndent);
+
+CF_EXTERN_C_END
+
+//%PDDM-DEFINE GPB_IVAR_ACCESSORS()
+//%// Getters and Setters for ivars named |name| from instance self.
+//%
+//%GPB_IVAR_ACCESSORS_DECL(Data, NSData*)
+//%GPB_IVAR_ACCESSORS_DECL(String, NSString*)
+//%GPB_IVAR_ACCESSORS_DECL(Message, GPBMessage*)
+//%GPB_IVAR_ACCESSORS_DECL(Group, GPBMessage*)
+//%GPB_IVAR_ACCESSORS_DECL(Bool, BOOL)
+//%GPB_IVAR_ACCESSORS_DECL(Int32, int32_t)
+//%GPB_IVAR_ACCESSORS_DECL(SFixed32, int32_t)
+//%GPB_IVAR_ACCESSORS_DECL(SInt32, int32_t)
+//%GPB_IVAR_ACCESSORS_DECL(Enum, int32_t)
+//%GPB_IVAR_ACCESSORS_DECL(UInt32, uint32_t)
+//%GPB_IVAR_ACCESSORS_DECL(Fixed32, uint32_t)
+//%GPB_IVAR_ACCESSORS_DECL(Int64, int64_t)
+//%GPB_IVAR_ACCESSORS_DECL(SInt64, int64_t)
+//%GPB_IVAR_ACCESSORS_DECL(SFixed64, int64_t)
+//%GPB_IVAR_ACCESSORS_DECL(UInt64, uint64_t)
+//%GPB_IVAR_ACCESSORS_DECL(Fixed64, uint64_t)
+//%GPB_IVAR_ACCESSORS_DECL(Float, float)
+//%GPB_IVAR_ACCESSORS_DECL(Double, double)
+//%PDDM-DEFINE GPB_IVAR_ACCESSORS_DECL(NAME, TYPE)
+//%TYPE GPBGet##NAME##IvarWithField(GPBMessage *self,
+//% TYPE$S NAME$S GPBFieldDescriptor *field);
+//%void GPBSet##NAME##IvarWithField(GPBMessage *self,
+//% NAME$S GPBFieldDescriptor *field,
+//% NAME$S TYPE value);
diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m
new file mode 100644
index 00000000..09e34bfb
--- /dev/null
+++ b/objectivec/GPBUtilities.m
@@ -0,0 +1,1645 @@
+// 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 "GPBUtilities_PackagePrivate.h"
+
+#import <objc/runtime.h>
+
+#import "GPBArray_PackagePrivate.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBDictionary_PackagePrivate.h"
+#import "GPBExtensionField.h"
+#import "GPBField.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUnknownFieldSet.h"
+
+static void AppendTextFormatForMessage(GPBMessage *message,
+ NSMutableString *toStr,
+ NSString *lineIndent);
+
+NSData *GPBEmptyNSData(void) {
+ static dispatch_once_t onceToken;
+ static NSData *defaultNSData = nil;
+ dispatch_once(&onceToken, ^{
+ defaultNSData = [[NSData alloc] init];
+ });
+ return defaultNSData;
+}
+
+BOOL GPBMessageHasFieldNumberSet(GPBMessage *self, uint32_t fieldNumber) {
+ GPBDescriptor *descriptor = [self descriptor];
+ GPBFieldDescriptor *field = [descriptor fieldWithNumber:fieldNumber];
+ return GPBMessageHasFieldSet(self, field);
+}
+
+BOOL GPBMessageHasFieldSet(GPBMessage *self, GPBFieldDescriptor *field) {
+ if (self == nil || field == nil) return NO;
+
+ // Repeated/Map don't use the bit, they check the count.
+ if (GPBFieldIsMapOrArray(field)) {
+ // Array/map type doesn't matter, since GPB*Array/NSArray and
+ // GPB*Dictionary/NSDictionary all support -count;
+ NSArray *arrayOrMap = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ return (arrayOrMap.count > 0);
+ } else {
+ return GPBGetHasIvarField(self, field);
+ }
+}
+
+void GPBClearMessageField(GPBMessage *self, GPBFieldDescriptor *field) {
+ // If not set, nothing to do.
+ if (!GPBGetHasIvarField(self, field)) {
+ return;
+ }
+
+ if (GPBFieldStoresObject(field)) {
+ // Object types are handled slightly differently, they need to be released.
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ id *typePtr = (id *)&storage[field->description_->offset];
+ [*typePtr release];
+ *typePtr = nil;
+ } else {
+ // POD types just need to clear the has bit as the Get* method will
+ // fetch the default when needed.
+ }
+ GPBSetHasIvarField(self, field, NO);
+}
+
+BOOL GPBGetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber) {
+ NSCAssert(self->messageStorage_ != NULL, @"How?");
+ if (idx < 0) {
+ NSCAssert(fieldNumber != 0, @"Invalid field number.");
+ BOOL hasIvar = (self->messageStorage_->_has_storage_[-idx] == fieldNumber);
+ return hasIvar;
+ } else {
+ NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
+ uint32_t byteIndex = idx / 32;
+ uint32_t bitMask = (1 << (idx % 32));
+ BOOL hasIvar =
+ (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO;
+ return hasIvar;
+ }
+}
+
+uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) {
+ NSCAssert(idx < 0, @"invalid index for oneof.");
+ uint32_t result = self->messageStorage_->_has_storage_[-idx];
+ return result;
+}
+
+void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber,
+ BOOL value) {
+ if (idx < 0) {
+ NSCAssert(fieldNumber != 0, @"Invalid field number.");
+ uint32_t *has_storage = self->messageStorage_->_has_storage_;
+ has_storage[-idx] = (value ? fieldNumber : 0);
+ } else {
+ NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
+ uint32_t *has_storage = self->messageStorage_->_has_storage_;
+ uint32_t byte = idx / 32;
+ uint32_t bitMask = (1 << (idx % 32));
+ if (value) {
+ has_storage[byte] |= bitMask;
+ } else {
+ has_storage[byte] &= ~bitMask;
+ }
+ }
+}
+
+void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
+ uint32_t fieldNumberNotToClear) {
+ int32_t hasIndex = oneof->oneofDescription_->index;
+ uint32_t fieldNumberSet = GPBGetHasOneof(self, hasIndex);
+ if ((fieldNumberSet == fieldNumberNotToClear) || (fieldNumberSet == 0)) {
+ // Do nothing/nothing set in the oneof.
+ return;
+ }
+
+ // Like GPBClearMessageField(), free the memory if an objecttype is set,
+ // pod types don't need to do anything.
+ GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet];
+ NSCAssert(fieldSet, @"oneof set to something not in the oneof?");
+ if (fieldSet && GPBFieldStoresObject(fieldSet)) {
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ id *typePtr = (id *)&storage[fieldSet->description_->offset];
+ [*typePtr release];
+ *typePtr = nil;
+ }
+
+ // Set to nothing stored in the oneof.
+ // (field number doesn't matter since setting to nothing).
+ GPBSetHasIvar(self, hasIndex, 1, NO);
+}
+
+#pragma mark - IVar accessors
+
+//%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE)
+//%TYPE GPBGet##NAME##IvarWithField(GPBMessage *self,
+//% TYPE$S NAME$S GPBFieldDescriptor *field) {
+//% if (GPBGetHasIvarField(self, field)) {
+//% uint8_t *storage = (uint8_t *)self->messageStorage_;
+//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
+//% return *typePtr;
+//% } else {
+//% return field.defaultValue.value##NAME;
+//% }
+//%}
+//%
+//%// Only exists for public api, no core code should use this.
+//%void GPBSet##NAME##IvarWithField(GPBMessage *self,
+//% NAME$S GPBFieldDescriptor *field,
+//% NAME$S TYPE value) {
+//% if (self == nil || field == nil) return;
+//% GPBFileSyntax syntax = [self descriptor].file.syntax;
+//% GPBSet##NAME##IvarWithFieldInternal(self, field, value, syntax);
+//%}
+//%
+//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self,
+//% NAME$S GPBFieldDescriptor *field,
+//% NAME$S TYPE value,
+//% NAME$S GPBFileSyntax syntax) {
+//% GPBOneofDescriptor *oneof = field->containingOneof_;
+//% if (oneof) {
+//% GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field));
+//% }
+//% NSCAssert(self->messageStorage_ != NULL, @"How?");
+//%#if defined(__clang_analyzer__)
+//% if (self->messageStorage_ == NULL) return;
+//%#endif
+//% uint8_t *storage = (uint8_t *)self->messageStorage_;
+//% TYPE *typePtr = (TYPE *)&storage[field->description_->offset];
+//% *typePtr = value;
+//% // proto2: any value counts as having been set; proto3, it
+//% // has to be a non zero value.
+//% BOOL hasValue =
+//% (syntax == GPBFileSyntaxProto2) || (value != (TYPE)0);
+//% GPBSetHasIvarField(self, field, hasValue);
+//% GPBBecomeVisibleToAutocreator(self);
+//%}
+//%
+//%PDDM-DEFINE IVAR_ALIAS_DEFN(NAME, ALIAS_NAME, TYPE, ALIAS_TYPE)
+//%// Only exists for public api, no core code should use this.
+//%TYPE GPBGet##NAME##IvarWithField(GPBMessage *self,
+//% TYPE$S NAME$S GPBFieldDescriptor *field) {
+//% return (TYPE)GPBGet##ALIAS_NAME##IvarWithField(self, field);
+//%}
+//%
+//%// Only exists for public api, no core code should use this.
+//%void GPBSet##NAME##IvarWithField(GPBMessage *self,
+//% NAME$S GPBFieldDescriptor *field,
+//% NAME$S TYPE value) {
+//% GPBSet##ALIAS_NAME##IvarWithField(self, field, (ALIAS_TYPE)value);
+//%}
+//%
+
+// Object types are handled slightly differently, they need to be released
+// and retained.
+
+void GPBSetAutocreatedRetainedObjectIvarWithField(
+ GPBMessage *self, GPBFieldDescriptor *field,
+ id __attribute__((ns_consumed)) value) {
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ id *typePtr = (id *)&storage[field->description_->offset];
+ NSCAssert(*typePtr == NULL, @"Can't set autocreated object more than once.");
+ *typePtr = value;
+}
+
+void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ if (GPBGetHasIvarField(self, field)) {
+ return;
+ }
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ id *typePtr = (id *)&storage[field->description_->offset];
+ GPBMessage *oldValue = *typePtr;
+ *typePtr = NULL;
+ GPBClearMessageAutocreator(oldValue);
+ [oldValue release];
+}
+
+// This exists only for briging some aliased types, nothing else should use it.
+GPB_INLINE void GPBSetObjectIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field, id value) {
+ if (self == nil || field == nil) return;
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
+ syntax);
+}
+
+void GPBSetObjectIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field, id value,
+ GPBFileSyntax syntax) {
+ GPBSetRetainedObjectIvarWithFieldInternal(self, field, [value retain],
+ syntax);
+}
+
+void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ id value, GPBFileSyntax syntax) {
+ NSCAssert(self->messageStorage_ != NULL, @"How?");
+#if defined(__clang_analyzer__)
+ if (self->messageStorage_ == NULL) return;
+#endif
+ GPBType fieldType = GPBGetFieldType(field);
+ BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
+ BOOL fieldIsMessage = GPBTypeIsMessage(fieldType);
+#ifdef DEBUG
+ if (value == nil && !isMapOrArray && !fieldIsMessage &&
+ field.hasDefaultValue) {
+ // Setting a message to nil is an obvious way to "clear" the value
+ // as there is no way to set a non-empty default value for messages.
+ //
+ // For Strings and Bytes that have default values set it is not clear what
+ // should be done when their value is set to nil. Is the intention just to
+ // clear the set value and reset to default, or is the intention to set the
+ // value to the empty string/data? Arguments can be made for both cases.
+ // 'nil' has been abused as a replacement for an empty string/data in ObjC.
+ // We decided to be consistent with all "object" types and clear the has
+ // field, and fall back on the default value. The warning below will only
+ // appear in debug, but the could should be changed so the intention is
+ // clear.
+ NSString *hasSel = NSStringFromSelector(field->hasSel_);
+ NSString *propName = field.name;
+ NSString *className = self.descriptor.name;
+ NSLog(@"warning: '%@.%@ = nil;' is not clearly defined for fields with "
+ @"default values. Please use '%@.%@ = %@' if you want to set it to "
+ @"empty, or call '%@.%@ = NO' to reset it to it's default value of "
+ @"'%@'. Defaulting to resetting default value.",
+ className, propName, className, propName,
+ (fieldType == GPBTypeString) ? @"@\"\"" : @"GPBEmptyNSData()",
+ className, hasSel, field.defaultValue.valueString);
+ // Note: valueString, depending on the type, it could easily be
+ // valueData/valueMessage.
+ }
+#endif // DEBUG
+ if (!isMapOrArray) {
+ // Non repeated/map can be in an oneof, clear any existing value from the
+ // oneof.
+ GPBOneofDescriptor *oneof = field->containingOneof_;
+ if (oneof) {
+ GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field));
+ }
+ // Clear "has" if they are being set to nil.
+ BOOL setHasValue = (value != nil);
+ // Under proto3, Data & String fields get cleared by resetting them to their
+ // default (empty) values, so if they are set to something of length zero,
+ // they are being cleared.
+ if ((syntax == GPBFileSyntaxProto3) && !fieldIsMessage &&
+ ([value length] == 0)) {
+ setHasValue = NO;
+ value = nil;
+ }
+ GPBSetHasIvarField(self, field, setHasValue);
+ }
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ id *typePtr = (id *)&storage[field->description_->offset];
+
+ id oldValue = *typePtr;
+
+ *typePtr = value;
+
+ if (oldValue) {
+ if (isMapOrArray) {
+ if (field.fieldType == GPBFieldTypeRepeated) {
+ // If the old message value was autocreated by us, then clear it.
+ if (GPBTypeIsObject(fieldType)) {
+ GPBAutocreatedArray *autoArray = oldValue;
+ if (autoArray->_autocreator == self) {
+ autoArray->_autocreator = nil;
+ }
+ } else {
+ // Type doesn't matter, it is a GPB*Array.
+ GPBInt32Array *gpbArray = oldValue;
+ if (gpbArray->_autocreator == self) {
+ gpbArray->_autocreator = nil;
+ }
+ }
+ }
+ } else if (fieldIsMessage) {
+ // If the old message value was autocreated by us, then clear it.
+ GPBMessage *oldMessageValue = oldValue;
+ if (GPBWasMessageAutocreatedBy(oldMessageValue, self)) {
+ GPBClearMessageAutocreator(oldMessageValue);
+ }
+ }
+ [oldValue release];
+ }
+
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ if (self->messageStorage_ == nil) {
+ return nil;
+ }
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ id *typePtr = (id *)&storage[field->description_->offset];
+ return *typePtr;
+}
+
+id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
+ NSCAssert(!GPBFieldIsMapOrArray(field), @"Shouldn't get here");
+ if (GPBGetHasIvarField(self, field)) {
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ id *typePtr = (id *)&storage[field->description_->offset];
+ return *typePtr;
+ }
+ // Not set...
+
+ // Non messages (string/data), get their default.
+ if (!GPBFieldTypeIsMessage(field)) {
+ return field.defaultValue.valueMessage;
+ }
+
+ OSSpinLockLock(&self->readOnlyMutex_);
+ GPBMessage *result = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+ if (!result) {
+ // For non repeated messages, create the object, set it and return it.
+ // This object will not initially be visible via GPBGetHasIvar, so
+ // we save its creator so it can become visible if it's mutated later.
+ result = GPBCreateMessageWithAutocreator(field.msgClass, self, field);
+ GPBSetAutocreatedRetainedObjectIvarWithField(self, field, result);
+ }
+ OSSpinLockUnlock(&self->readOnlyMutex_);
+ return result;
+}
+
+// Only exists for public api, no core code should use this.
+int32_t GPBGetEnumIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ return GPBGetEnumIvarWithFieldInternal(self, field, syntax);
+}
+
+int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ GPBFileSyntax syntax) {
+ int32_t result = GPBGetInt32IvarWithField(self, field);
+ // If this is presevering unknown enums, make sure the value is
+ // valid before returning it.
+ if (GPBHasPreservingUnknownEnumSemantics(syntax) &&
+ ![field isValidEnumValue:result]) {
+ result = kGPBUnrecognizedEnumeratorValue;
+ }
+ return result;
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetEnumIvarWithField(GPBMessage *self, GPBFieldDescriptor *field,
+ int32_t value) {
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetEnumIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field, int32_t value,
+ GPBFileSyntax syntax) {
+ // Don't allow in unknown values. Proto3 can use the Raw method.
+ if (![field isValidEnumValue:value]) {
+ [NSException raise:NSInvalidArgumentException
+ format:@"%@.%@: Attempt to set an unknown enum value (%d)",
+ [self class], field.name, value];
+ }
+ GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Bool, BOOL)
+// This block of code is generated, do not edit it directly.
+
+BOOL GPBGetBoolIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ if (GPBGetHasIvarField(self, field)) {
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ BOOL *typePtr = (BOOL *)&storage[field->description_->offset];
+ return *typePtr;
+ } else {
+ return field.defaultValue.valueBool;
+ }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetBoolIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ BOOL value) {
+ if (self == nil || field == nil) return;
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ GPBSetBoolIvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ BOOL value,
+ GPBFileSyntax syntax) {
+ GPBOneofDescriptor *oneof = field->containingOneof_;
+ if (oneof) {
+ GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field));
+ }
+ NSCAssert(self->messageStorage_ != NULL, @"How?");
+#if defined(__clang_analyzer__)
+ if (self->messageStorage_ == NULL) return;
+#endif
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ BOOL *typePtr = (BOOL *)&storage[field->description_->offset];
+ *typePtr = value;
+ // proto2: any value counts as having been set; proto3, it
+ // has to be a non zero value.
+ BOOL hasValue =
+ (syntax == GPBFileSyntaxProto2) || (value != (BOOL)0);
+ GPBSetHasIvarField(self, field, hasValue);
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t)
+// This block of code is generated, do not edit it directly.
+
+int32_t GPBGetInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ if (GPBGetHasIvarField(self, field)) {
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
+ return *typePtr;
+ } else {
+ return field.defaultValue.valueInt32;
+ }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value) {
+ if (self == nil || field == nil) return;
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ GPBSetInt32IvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value,
+ GPBFileSyntax syntax) {
+ GPBOneofDescriptor *oneof = field->containingOneof_;
+ if (oneof) {
+ GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field));
+ }
+ NSCAssert(self->messageStorage_ != NULL, @"How?");
+#if defined(__clang_analyzer__)
+ if (self->messageStorage_ == NULL) return;
+#endif
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ int32_t *typePtr = (int32_t *)&storage[field->description_->offset];
+ *typePtr = value;
+ // proto2: any value counts as having been set; proto3, it
+ // has to be a non zero value.
+ BOOL hasValue =
+ (syntax == GPBFileSyntaxProto2) || (value != (int32_t)0);
+ GPBSetHasIvarField(self, field, hasValue);
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+uint32_t GPBGetUInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ if (GPBGetHasIvarField(self, field)) {
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
+ return *typePtr;
+ } else {
+ return field.defaultValue.valueUInt32;
+ }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetUInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint32_t value) {
+ if (self == nil || field == nil) return;
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ GPBSetUInt32IvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint32_t value,
+ GPBFileSyntax syntax) {
+ GPBOneofDescriptor *oneof = field->containingOneof_;
+ if (oneof) {
+ GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field));
+ }
+ NSCAssert(self->messageStorage_ != NULL, @"How?");
+#if defined(__clang_analyzer__)
+ if (self->messageStorage_ == NULL) return;
+#endif
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ uint32_t *typePtr = (uint32_t *)&storage[field->description_->offset];
+ *typePtr = value;
+ // proto2: any value counts as having been set; proto3, it
+ // has to be a non zero value.
+ BOOL hasValue =
+ (syntax == GPBFileSyntaxProto2) || (value != (uint32_t)0);
+ GPBSetHasIvarField(self, field, hasValue);
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t)
+// This block of code is generated, do not edit it directly.
+
+int64_t GPBGetInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ if (GPBGetHasIvarField(self, field)) {
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
+ return *typePtr;
+ } else {
+ return field.defaultValue.valueInt64;
+ }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int64_t value) {
+ if (self == nil || field == nil) return;
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ GPBSetInt64IvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int64_t value,
+ GPBFileSyntax syntax) {
+ GPBOneofDescriptor *oneof = field->containingOneof_;
+ if (oneof) {
+ GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field));
+ }
+ NSCAssert(self->messageStorage_ != NULL, @"How?");
+#if defined(__clang_analyzer__)
+ if (self->messageStorage_ == NULL) return;
+#endif
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ int64_t *typePtr = (int64_t *)&storage[field->description_->offset];
+ *typePtr = value;
+ // proto2: any value counts as having been set; proto3, it
+ // has to be a non zero value.
+ BOOL hasValue =
+ (syntax == GPBFileSyntaxProto2) || (value != (int64_t)0);
+ GPBSetHasIvarField(self, field, hasValue);
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+uint64_t GPBGetUInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ if (GPBGetHasIvarField(self, field)) {
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
+ return *typePtr;
+ } else {
+ return field.defaultValue.valueUInt64;
+ }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetUInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint64_t value) {
+ if (self == nil || field == nil) return;
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ GPBSetUInt64IvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint64_t value,
+ GPBFileSyntax syntax) {
+ GPBOneofDescriptor *oneof = field->containingOneof_;
+ if (oneof) {
+ GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field));
+ }
+ NSCAssert(self->messageStorage_ != NULL, @"How?");
+#if defined(__clang_analyzer__)
+ if (self->messageStorage_ == NULL) return;
+#endif
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ uint64_t *typePtr = (uint64_t *)&storage[field->description_->offset];
+ *typePtr = value;
+ // proto2: any value counts as having been set; proto3, it
+ // has to be a non zero value.
+ BOOL hasValue =
+ (syntax == GPBFileSyntaxProto2) || (value != (uint64_t)0);
+ GPBSetHasIvarField(self, field, hasValue);
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float)
+// This block of code is generated, do not edit it directly.
+
+float GPBGetFloatIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ if (GPBGetHasIvarField(self, field)) {
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ float *typePtr = (float *)&storage[field->description_->offset];
+ return *typePtr;
+ } else {
+ return field.defaultValue.valueFloat;
+ }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetFloatIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ float value) {
+ if (self == nil || field == nil) return;
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ GPBSetFloatIvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ float value,
+ GPBFileSyntax syntax) {
+ GPBOneofDescriptor *oneof = field->containingOneof_;
+ if (oneof) {
+ GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field));
+ }
+ NSCAssert(self->messageStorage_ != NULL, @"How?");
+#if defined(__clang_analyzer__)
+ if (self->messageStorage_ == NULL) return;
+#endif
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ float *typePtr = (float *)&storage[field->description_->offset];
+ *typePtr = value;
+ // proto2: any value counts as having been set; proto3, it
+ // has to be a non zero value.
+ BOOL hasValue =
+ (syntax == GPBFileSyntaxProto2) || (value != (float)0);
+ GPBSetHasIvarField(self, field, hasValue);
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double)
+// This block of code is generated, do not edit it directly.
+
+double GPBGetDoubleIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ if (GPBGetHasIvarField(self, field)) {
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ double *typePtr = (double *)&storage[field->description_->offset];
+ return *typePtr;
+ } else {
+ return field.defaultValue.valueDouble;
+ }
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetDoubleIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ double value) {
+ if (self == nil || field == nil) return;
+ GPBFileSyntax syntax = [self descriptor].file.syntax;
+ GPBSetDoubleIvarWithFieldInternal(self, field, value, syntax);
+}
+
+void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ double value,
+ GPBFileSyntax syntax) {
+ GPBOneofDescriptor *oneof = field->containingOneof_;
+ if (oneof) {
+ GPBMaybeClearOneof(self, oneof, GPBFieldNumber(field));
+ }
+ NSCAssert(self->messageStorage_ != NULL, @"How?");
+#if defined(__clang_analyzer__)
+ if (self->messageStorage_ == NULL) return;
+#endif
+ uint8_t *storage = (uint8_t *)self->messageStorage_;
+ double *typePtr = (double *)&storage[field->description_->offset];
+ *typePtr = value;
+ // proto2: any value counts as having been set; proto3, it
+ // has to be a non zero value.
+ BOOL hasValue =
+ (syntax == GPBFileSyntaxProto2) || (value != (double)0);
+ GPBSetHasIvarField(self, field, hasValue);
+ GPBBecomeVisibleToAutocreator(self);
+}
+
+//%PDDM-EXPAND-END (7 expansions)
+
+// Aliases are function calls that are virtually the same.
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN(SInt32, Int32, int32_t, int32_t)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+int32_t GPBGetSInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ return (int32_t)GPBGetInt32IvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetSInt32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value) {
+ GPBSetInt32IvarWithField(self, field, (int32_t)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN(SFixed32, Int32, int32_t, int32_t)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+int32_t GPBGetSFixed32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ return (int32_t)GPBGetInt32IvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetSFixed32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value) {
+ GPBSetInt32IvarWithField(self, field, (int32_t)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN(Fixed32, UInt32, uint32_t, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+uint32_t GPBGetFixed32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ return (uint32_t)GPBGetUInt32IvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetFixed32IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint32_t value) {
+ GPBSetUInt32IvarWithField(self, field, (uint32_t)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN(SInt64, Int64, int64_t, int64_t)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+int64_t GPBGetSInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ return (int64_t)GPBGetInt64IvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetSInt64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int64_t value) {
+ GPBSetInt64IvarWithField(self, field, (int64_t)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN(SFixed64, Int64, int64_t, int64_t)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+int64_t GPBGetSFixed64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ return (int64_t)GPBGetInt64IvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetSFixed64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int64_t value) {
+ GPBSetInt64IvarWithField(self, field, (int64_t)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN(Fixed64, UInt64, uint64_t, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+uint64_t GPBGetFixed64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ return (uint64_t)GPBGetUInt64IvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetFixed64IvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint64_t value) {
+ GPBSetUInt64IvarWithField(self, field, (uint64_t)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN(String, Object, NSString*, id)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+NSString* GPBGetStringIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ return (NSString*)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetStringIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ NSString* value) {
+ GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN(Data, Object, NSData*, id)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+NSData* GPBGetDataIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ return (NSData*)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetDataIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ NSData* value) {
+ GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN(Message, Object, GPBMessage*, id)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+GPBMessage* GPBGetMessageIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ return (GPBMessage*)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetMessageIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ GPBMessage* value) {
+ GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND IVAR_ALIAS_DEFN(Group, Object, GPBMessage*, id)
+// This block of code is generated, do not edit it directly.
+
+// Only exists for public api, no core code should use this.
+GPBMessage* GPBGetGroupIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field) {
+ return (GPBMessage*)GPBGetObjectIvarWithField(self, field);
+}
+
+// Only exists for public api, no core code should use this.
+void GPBSetGroupIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ GPBMessage* value) {
+ GPBSetObjectIvarWithField(self, field, (id)value);
+}
+
+//%PDDM-EXPAND-END (10 expansions)
+
+#pragma mark - Misc Dynamic Runtime Utils
+
+void GPBApplyFunctionsToMessageFields(GPBApplyFunctions *functions,
+ GPBMessage *msg, void *context) {
+ GPBDescriptor *descriptor = [[msg class] descriptor];
+ for (GPBFieldDescriptor *field in descriptor->fields_) {
+ BOOL wasGood;
+ if (GPBFieldIsMapOrArray(field)) {
+ wasGood = (*functions)[GPBApplyFunctionObject](field, context);
+ } else {
+ wasGood = GPBApplyFunctionsBasedOnField(field, functions, context);
+ }
+ if (!wasGood) {
+ break;
+ }
+ }
+}
+
+BOOL GPBApplyFunctionsBasedOnField(GPBFieldDescriptor *field,
+ GPBApplyFunctions *functions,
+ void *context) {
+ static const GPBApplyFunctionOrder typeMap[GPBTypeCount] = {
+ GPBApplyFunctionBool,
+ GPBApplyFunctionUInt32,
+ GPBApplyFunctionInt32,
+ GPBApplyFunctionFloat,
+ GPBApplyFunctionUInt64,
+ GPBApplyFunctionInt64,
+ GPBApplyFunctionDouble,
+ GPBApplyFunctionInt32,
+ GPBApplyFunctionInt64,
+ GPBApplyFunctionInt32,
+ GPBApplyFunctionInt64,
+ GPBApplyFunctionUInt32,
+ GPBApplyFunctionUInt64,
+ GPBApplyFunctionObject,
+ GPBApplyFunctionObject,
+ GPBApplyFunctionObject,
+ GPBApplyFunctionObject,
+ GPBApplyFunctionInt32
+ };
+ return (*functions)[typeMap[GPBGetFieldType(field)]](field, context);
+}
+
+void GPBApplyStrictFunctionsToMessageFields(GPBApplyStrictFunctions *functions,
+ GPBMessage *msg, void *context) {
+ GPBDescriptor *descriptor = [[msg class] descriptor];
+ for (GPBFieldDescriptor *fieldDescriptor in descriptor->fields_) {
+ GPBApplyFunction function = (*functions)[GPBGetFieldType(fieldDescriptor)];
+ BOOL wasGood = function(fieldDescriptor, context);
+ if (!wasGood) {
+ break;
+ }
+ }
+}
+
+const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) {
+ Protocol *protocol =
+ objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol));
+ struct objc_method_description description =
+ protocol_getMethodDescription(protocol, selector, NO, instanceSel);
+ return description.types;
+}
+
+#pragma mark - Text Format Support
+
+static void AppendStringEscaped(NSString *toPrint, NSMutableString *destStr) {
+ [destStr appendString:@"\""];
+ NSUInteger len = [toPrint length];
+ for (NSUInteger i = 0; i < len; ++i) {
+ unichar aChar = [toPrint characterAtIndex:i];
+ switch (aChar) {
+ case '\n': [destStr appendString:@"\\n"]; break;
+ case '\r': [destStr appendString:@"\\r"]; break;
+ case '\t': [destStr appendString:@"\\t"]; break;
+ case '\"': [destStr appendString:@"\\\""]; break;
+ case '\'': [destStr appendString:@"\\\'"]; break;
+ case '\\': [destStr appendString:@"\\\\"]; break;
+ default:
+ [destStr appendFormat:@"%C", aChar];
+ break;
+ }
+ }
+ [destStr appendString:@"\""];
+}
+
+static void AppendBufferAsString(NSData *buffer, NSMutableString *destStr) {
+ const char *src = (const char *)[buffer bytes];
+ size_t srcLen = [buffer length];
+ [destStr appendString:@"\""];
+ for (const char *srcEnd = src + srcLen; src < srcEnd; src++) {
+ switch (*src) {
+ case '\n': [destStr appendString:@"\\n"]; break;
+ case '\r': [destStr appendString:@"\\r"]; break;
+ case '\t': [destStr appendString:@"\\t"]; break;
+ case '\"': [destStr appendString:@"\\\""]; break;
+ case '\'': [destStr appendString:@"\\\'"]; break;
+ case '\\': [destStr appendString:@"\\\\"]; break;
+ default:
+ if (isprint(*src)) {
+ [destStr appendFormat:@"%c", *src];
+ } else {
+ // NOTE: doing hex means you have to worry about the letter after
+ // the hex being another hex char and forcing that to be escaped, so
+ // use octal to keep it simple.
+ [destStr appendFormat:@"\\%03o", (uint8_t)(*src)];
+ }
+ break;
+ }
+ }
+ [destStr appendString:@"\""];
+}
+
+static void AppendTextFormatForMapMessageField(
+ id map, GPBFieldDescriptor *field, NSMutableString *toStr,
+ NSString *lineIndent, NSString *fieldName, NSString *lineEnding) {
+ GPBType keyType = field.mapKeyType;
+ GPBType valueType = GPBGetFieldType(field);
+ BOOL isMessageValue = GPBTypeIsMessage(valueType);
+
+ NSString *msgStartFirst =
+ [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding];
+ NSString *msgStart =
+ [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName];
+ NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent];
+
+ NSString *keyLine = [NSString stringWithFormat:@"%@ key: ", lineIndent];
+ NSString *valueLine = [NSString stringWithFormat:@"%@ value%s ", lineIndent,
+ (isMessageValue ? "" : ":")];
+
+ __block BOOL isFirst = YES;
+
+ if ((keyType == GPBTypeString) && GPBTypeIsObject(valueType)) {
+ // map is an NSDictionary.
+ NSDictionary *dict = map;
+ [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
+ #pragma unused(stop)
+ [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
+ isFirst = NO;
+
+ [toStr appendString:keyLine];
+ AppendStringEscaped(key, toStr);
+ [toStr appendString:@"\n"];
+
+ [toStr appendString:valueLine];
+ switch (valueType) {
+ case GPBTypeString:
+ AppendStringEscaped(value, toStr);
+ break;
+
+ case GPBTypeData:
+ AppendBufferAsString(value, toStr);
+ break;
+
+ case GPBTypeMessage:
+ [toStr appendString:@"{\n"];
+ NSString *subIndent = [lineIndent stringByAppendingString:@" "];
+ AppendTextFormatForMessage(value, toStr, subIndent);
+ [toStr appendFormat:@"%@ }", lineIndent];
+ break;
+
+ default:
+ NSCAssert(NO, @"Can't happen");
+ break;
+ }
+ [toStr appendString:@"\n"];
+
+ [toStr appendString:msgEnd];
+ }];
+ } else {
+ // map is one of the GPB*Dictionary classes, type doesn't matter.
+ GPBInt32Int32Dictionary *dict = map;
+ [dict enumerateForTextFormat:^(id keyObj, id valueObj) {
+ [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
+ isFirst = NO;
+
+ // Key always is a NSString.
+ if (keyType == GPBTypeString) {
+ [toStr appendString:keyLine];
+ AppendStringEscaped(keyObj, toStr);
+ [toStr appendString:@"\n"];
+ } else {
+ [toStr appendFormat:@"%@%@\n", keyLine, keyObj];
+ }
+
+ [toStr appendString:valueLine];
+ switch (valueType) {
+ case GPBTypeString:
+ AppendStringEscaped(valueObj, toStr);
+ break;
+
+ case GPBTypeData:
+ AppendBufferAsString(valueObj, toStr);
+ break;
+
+ case GPBTypeMessage:
+ [toStr appendString:@"{\n"];
+ NSString *subIndent = [lineIndent stringByAppendingString:@" "];
+ AppendTextFormatForMessage(valueObj, toStr, subIndent);
+ [toStr appendFormat:@"%@ }", lineIndent];
+ break;
+
+ case GPBTypeEnum: {
+ int32_t enumValue = [valueObj intValue];
+ NSString *valueStr = nil;
+ GPBEnumDescriptor *descriptor = field.enumDescriptor;
+ if (descriptor) {
+ valueStr = [descriptor textFormatNameForValue:enumValue];
+ }
+ if (valueStr) {
+ [toStr appendString:valueStr];
+ } else {
+ [toStr appendFormat:@"%d", enumValue];
+ }
+ break;
+ }
+
+ default:
+ NSCAssert(valueType != GPBTypeGroup, @"Can't happen");
+ // Everything else is a NSString.
+ [toStr appendString:valueObj];
+ break;
+ }
+ [toStr appendString:@"\n"];
+
+ [toStr appendString:msgEnd];
+ }];
+ }
+}
+
+static void AppendTextFormatForMessageField(GPBMessage *message,
+ GPBFieldDescriptor *field,
+ NSMutableString *toStr,
+ NSString *lineIndent) {
+ id array;
+ NSUInteger arrayCount;
+ GPBFieldType fieldType = field.fieldType;
+ switch (fieldType) {
+ case GPBFieldTypeSingle:
+ array = nil;
+ arrayCount = (GPBGetHasIvarField(message, field) ? 1 : 0);
+ break;
+
+ case GPBFieldTypeRepeated:
+ array = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
+ arrayCount = [(NSArray *)array count];
+ break;
+
+ case GPBFieldTypeMap: {
+ // Could be a GPB*Dictionary or NSMutableDictionary, type doesn't matter,
+ // just want count.
+ array = GPBGetObjectIvarWithFieldNoAutocreate(message, field);
+ arrayCount = [(NSArray *)array count];
+ break;
+ }
+ }
+
+ if (arrayCount == 0) {
+ // Nothing to print, out of here.
+ return;
+ }
+
+ NSString *lineEnding = @"";
+
+ // If the name can't be reversed or support for extra info was turned off,
+ // this can return nil.
+ NSString *fieldName = [field textFormatName];
+ if ([fieldName length] == 0) {
+ fieldName = [NSString stringWithFormat:@"%u", GPBFieldNumber(field)];
+ // If there is only one entry, put the objc name as a comment, other wise
+ // add it before the the repeated values.
+ if (arrayCount > 1) {
+ [toStr appendFormat:@"%@# %@\n", lineIndent, field.name];
+ } else {
+ lineEnding = [NSString stringWithFormat:@" # %@", field.name];
+ }
+ }
+
+ if (fieldType == GPBFieldTypeMap) {
+ AppendTextFormatForMapMessageField(array, field, toStr, lineIndent,
+ fieldName, lineEnding);
+ return;
+ }
+
+ const BOOL isRepeated = (array != nil);
+
+ GPBType fieldDataType = GPBGetFieldType(field);
+ BOOL isMessageField = GPBTypeIsMessage(fieldDataType);
+ for (NSUInteger j = 0; j < arrayCount; ++j) {
+ // Start the line.
+ [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName,
+ (isMessageField ? "" : ":")];
+
+ // The value.
+ switch (fieldDataType) {
+#define FIELD_CASE(GPBTYPE, CTYPE, ARRAY_TYPE, ...) \
+ case GPBType##GPBTYPE: { \
+ CTYPE v = (isRepeated ? [(GPB##ARRAY_TYPE##Array *)array valueAtIndex:j] \
+ : GPBGet##GPBTYPE##IvarWithField(message, field)); \
+ [toStr appendFormat:__VA_ARGS__, v]; \
+ break; \
+ }
+
+ FIELD_CASE(Int32, int32_t, Int32, @"%d")
+ FIELD_CASE(SInt32, int32_t, Int32, @"%d")
+ FIELD_CASE(SFixed32, int32_t, Int32, @"%d")
+ FIELD_CASE(UInt32, uint32_t, UInt32, @"%u")
+ FIELD_CASE(Fixed32, uint32_t, UInt32, @"%u")
+ FIELD_CASE(Int64, int64_t, Int64, @"%lld")
+ FIELD_CASE(SInt64, int64_t, Int64, @"%lld")
+ FIELD_CASE(SFixed64, int64_t, Int64, @"%lld")
+ FIELD_CASE(UInt64, uint64_t, UInt64, @"%llu")
+ FIELD_CASE(Fixed64, uint64_t, UInt64, @"%llu")
+ FIELD_CASE(Float, float, Float, @"%.*g", FLT_DIG)
+ FIELD_CASE(Double, double, Double, @"%.*lg", DBL_DIG)
+
+#undef FIELD_CASE
+
+ case GPBTypeEnum: {
+ int32_t v = (isRepeated ? [(GPBEnumArray *)array rawValueAtIndex:j]
+ : GPBGetInt32IvarWithField(message, field));
+ NSString *valueStr = nil;
+ GPBEnumDescriptor *descriptor = field.enumDescriptor;
+ if (descriptor) {
+ valueStr = [descriptor textFormatNameForValue:v];
+ }
+ if (valueStr) {
+ [toStr appendString:valueStr];
+ } else {
+ [toStr appendFormat:@"%d", v];
+ }
+ break;
+ }
+
+ case GPBTypeBool: {
+ BOOL v = (isRepeated ? [(GPBBoolArray *)array valueAtIndex:j]
+ : GPBGetBoolIvarWithField(message, field));
+ [toStr appendString:(v ? @"true" : @"false")];
+ break;
+ }
+
+ case GPBTypeString: {
+ NSString *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
+ : GPBGetStringIvarWithField(message, field));
+ AppendStringEscaped(v, toStr);
+ break;
+ }
+
+ case GPBTypeData: {
+ NSData *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
+ : GPBGetDataIvarWithField(message, field));
+ AppendBufferAsString(v, toStr);
+ break;
+ }
+
+ case GPBTypeGroup:
+ case GPBTypeMessage: {
+ GPBMessage *v =
+ (isRepeated ? [(NSArray *)array objectAtIndex:j]
+ : GPBGetObjectIvarWithField(message, field));
+ [toStr appendFormat:@"{%@\n", lineEnding];
+ NSString *subIndent = [lineIndent stringByAppendingString:@" "];
+ AppendTextFormatForMessage(v, toStr, subIndent);
+ [toStr appendFormat:@"%@}", lineIndent];
+ lineEnding = @"";
+ break;
+ }
+
+ } // switch(fieldDataType)
+
+ // End the line.
+ [toStr appendFormat:@"%@\n", lineEnding];
+
+ } // for(arrayCount)
+}
+
+static void AppendTextFormatForMessageExtensionRange(GPBMessage *message,
+ NSArray *activeExtensions,
+ GPBExtensionRange range,
+ NSMutableString *toStr,
+ NSString *lineIndent) {
+ uint32_t start = range.start;
+ uint32_t end = range.end;
+ for (GPBExtensionField *extension in activeExtensions) {
+ uint32_t fieldNumber = extension.fieldNumber;
+ if (fieldNumber < start) {
+ // Not there yet.
+ continue;
+ }
+ if (fieldNumber > end) {
+ // Done.
+ break;
+ }
+
+ id rawExtValue = [message getExtension:extension];
+ GPBExtensionDescriptor *extDescriptor = [extension descriptor];
+ BOOL isRepeated = extDescriptor.isRepeated;
+
+ NSUInteger numValues = 1;
+ NSString *lineEnding = @"";
+ if (isRepeated) {
+ numValues = [(NSArray *)rawExtValue count];
+ }
+
+ NSString *singletonName = extension.descriptor.singletonName;
+ if (numValues == 1) {
+ lineEnding = [NSString stringWithFormat:@" # [%@]", singletonName];
+ } else {
+ [toStr appendFormat:@"%@# [%@]\n", lineIndent, singletonName];
+ }
+
+ GPBType extType = extDescriptor.type;
+ for (NSUInteger j = 0; j < numValues; ++j) {
+ id curValue = (isRepeated ? [rawExtValue objectAtIndex:j] : rawExtValue);
+
+ // Start the line.
+ [toStr appendFormat:@"%@%u%s ", lineIndent, fieldNumber,
+ (GPBTypeIsMessage(extType) ? "" : ":")];
+
+ // The value.
+ switch (extType) {
+#define FIELD_CASE(GPBTYPE, CTYPE, NUMSELECTOR, ...) \
+ case GPBType##GPBTYPE: { \
+ CTYPE v = [(NSNumber *)curValue NUMSELECTOR]; \
+ [toStr appendFormat:__VA_ARGS__, v]; \
+ break; \
+ }
+
+ FIELD_CASE(Int32, int32_t, intValue, @"%d")
+ FIELD_CASE(SInt32, int32_t, intValue, @"%d")
+ FIELD_CASE(SFixed32, int32_t, unsignedIntValue, @"%d")
+ FIELD_CASE(UInt32, uint32_t, unsignedIntValue, @"%u")
+ FIELD_CASE(Fixed32, uint32_t, unsignedIntValue, @"%u")
+ FIELD_CASE(Int64, int64_t, longLongValue, @"%lld")
+ FIELD_CASE(SInt64, int64_t, longLongValue, @"%lld")
+ FIELD_CASE(SFixed64, int64_t, longLongValue, @"%lld")
+ FIELD_CASE(UInt64, uint64_t, unsignedLongLongValue, @"%llu")
+ FIELD_CASE(Fixed64, uint64_t, unsignedLongLongValue, @"%llu")
+ FIELD_CASE(Float, float, floatValue, @"%.*g", FLT_DIG)
+ FIELD_CASE(Double, double, doubleValue, @"%.*lg", DBL_DIG)
+ // TODO: Add a comment with the enum name from enum descriptors
+ // (might not be real value, so leave it as a comment, ObjC compiler
+ // name mangles differently). Doesn't look like we actually generate
+ // an enum descriptor reference like we do for normal fields, so this
+ // will take a compiler change.
+ FIELD_CASE(Enum, int32_t, intValue, @"%d")
+
+#undef FIELD_CASE
+
+ case GPBTypeBool:
+ [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true"
+ : @"false")];
+ break;
+
+ case GPBTypeString:
+ AppendStringEscaped(curValue, toStr);
+ break;
+
+ case GPBTypeData:
+ AppendBufferAsString((NSData *)curValue, toStr);
+ break;
+
+ case GPBTypeGroup:
+ case GPBTypeMessage: {
+ [toStr appendFormat:@"{%@\n", lineEnding];
+ NSString *subIndent = [lineIndent stringByAppendingString:@" "];
+ AppendTextFormatForMessage(curValue, toStr, subIndent);
+ [toStr appendFormat:@"%@}", lineIndent];
+ lineEnding = @"";
+ break;
+ }
+
+ } // switch(extType)
+
+ } // for(numValues)
+
+ // End the line.
+ [toStr appendFormat:@"%@\n", lineEnding];
+
+ } // for..in(activeExtensions)
+}
+
+static void AppendTextFormatForMessage(GPBMessage *message,
+ NSMutableString *toStr,
+ NSString *lineIndent) {
+ GPBDescriptor *descriptor = [message descriptor];
+ NSArray *fieldsArray = descriptor->fields_;
+ NSUInteger fieldCount = fieldsArray.count;
+ const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
+ NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
+ NSArray *activeExtensions = [message sortedExtensionsInUse];
+ for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
+ if (i == fieldCount) {
+ AppendTextFormatForMessageExtensionRange(
+ message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
+ } else if (j == extensionRangesCount ||
+ GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
+ AppendTextFormatForMessageField(message, fieldsArray[i++], toStr,
+ lineIndent);
+ } else {
+ AppendTextFormatForMessageExtensionRange(
+ message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
+ }
+ }
+
+ NSString *unknownFieldsStr =
+ GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent);
+ if ([unknownFieldsStr length] > 0) {
+ [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent];
+ [toStr appendString:unknownFieldsStr];
+ }
+}
+
+NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *lineIndent) {
+ if (message == nil) return nil;
+ if (lineIndent == nil) lineIndent = @"";
+
+ NSMutableString *buildString = [NSMutableString string];
+ AppendTextFormatForMessage(message, buildString, lineIndent);
+ return buildString;
+}
+
+NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet,
+ NSString *lineIndent) {
+ if (unknownSet == nil) return nil;
+ if (lineIndent == nil) lineIndent = @"";
+
+ NSMutableString *result = [NSMutableString string];
+ for (GPBField *field in [unknownSet sortedFields]) {
+ int32_t fieldNumber = [field number];
+
+#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT) \
+ [field.PROPNAME \
+ enumerateValuesWithBlock:^(CTYPE value, NSUInteger idx, BOOL * stop) { \
+ _Pragma("unused(idx, stop)"); \
+ [result \
+ appendFormat:@"%@%d: " #FORMAT "\n", lineIndent, fieldNumber, value]; \
+ }];
+
+ PRINT_LOOP(varintList, uint64_t, %llu);
+ PRINT_LOOP(fixed32List, uint32_t, 0x%X);
+ PRINT_LOOP(fixed64List, uint64_t, 0x%llX);
+
+#undef PRINT_LOOP
+
+ // NOTE: C++ version of TextFormat tries to parse this as a message
+ // and print that if it succeeds.
+ for (NSData *data in field.lengthDelimitedList) {
+ [result appendFormat:@"%@%d: ", lineIndent, fieldNumber];
+ AppendBufferAsString(data, result);
+ [result appendString:@"\n"];
+ }
+
+ for (GPBUnknownFieldSet *subUnknownSet in field.groupList) {
+ [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber];
+ NSString *subIndent = [lineIndent stringByAppendingString:@" "];
+ NSString *subUnknwonSetStr =
+ GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent);
+ [result appendString:subUnknwonSetStr];
+ [result appendFormat:@"%@}\n", lineIndent];
+ }
+ }
+ return result;
+}
+
+// Helpers to decode a varint. Not using GPBCodedInputStream version because
+// that needs a state object, and we don't want to create an input stream out
+// of the data.
+static inline int8_t ReadRawByteFromData(const uint8_t **data) {
+ int8_t result = *((int8_t *)(*data));
+ ++(*data);
+ return result;
+}
+
+static inline int32_t ReadRawVarint32FromData(const uint8_t **data) {
+ int8_t tmp = ReadRawByteFromData(data);
+ if (tmp >= 0) {
+ return tmp;
+ }
+ int32_t result = tmp & 0x7f;
+ if ((tmp = ReadRawByteFromData(data)) >= 0) {
+ result |= tmp << 7;
+ } else {
+ result |= (tmp & 0x7f) << 7;
+ if ((tmp = ReadRawByteFromData(data)) >= 0) {
+ result |= tmp << 14;
+ } else {
+ result |= (tmp & 0x7f) << 14;
+ if ((tmp = ReadRawByteFromData(data)) >= 0) {
+ result |= tmp << 21;
+ } else {
+ result |= (tmp & 0x7f) << 21;
+ result |= (tmp = ReadRawByteFromData(data)) << 28;
+ if (tmp < 0) {
+ // Discard upper 32 bits.
+ for (int i = 0; i < 5; i++) {
+ if (ReadRawByteFromData(data) >= 0) {
+ return result;
+ }
+ }
+ [NSException raise:NSParseErrorException
+ format:@"Unable to read varint32"];
+ }
+ }
+ }
+ }
+ return result;
+}
+
+NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
+ NSString *inputStr) {
+ // decodData form:
+ // varint32: num entries
+ // for each entry:
+ // varint32: key
+ // bytes*: decode data
+ //
+ // decode data one of two forms:
+ // 1: a \0 followed by the string followed by an \0
+ // 2: bytecodes to transform an input into the right thing, ending with \0
+ //
+ // the bytes codes are of the form:
+ // 0xabbccccc
+ // 0x0 (all zeros), end.
+ // a - if set, add an underscore
+ // bb - 00 ccccc bytes as is
+ // bb - 10 ccccc upper first, as is on rest, ccccc byte total
+ // bb - 01 ccccc lower first, as is on rest, ccccc byte total
+ // bb - 11 ccccc all upper, ccccc byte total
+
+ if (!decodeData || !inputStr) {
+ return nil;
+ }
+
+ // Find key
+ const uint8_t *scan = decodeData;
+ int32_t numEntries = ReadRawVarint32FromData(&scan);
+ BOOL foundKey = NO;
+ while (!foundKey && (numEntries > 0)) {
+ --numEntries;
+ int32_t dataKey = ReadRawVarint32FromData(&scan);
+ if (dataKey == key) {
+ foundKey = YES;
+ } else {
+ // If it is a inlined string, it will start with \0; if it is bytecode it
+ // will start with a code. So advance one (skipping the inline string
+ // marker), and then loop until reaching the end marker (\0).
+ ++scan;
+ while (*scan != 0) ++scan;
+ // Now move past the end marker.
+ ++scan;
+ }
+ }
+
+ if (!foundKey) {
+ return nil;
+ }
+
+ // Decode
+
+ if (*scan == 0) {
+ // Inline string. Move over the marker, and NSString can take it as
+ // UTF8.
+ ++scan;
+ NSString *result = [NSString stringWithUTF8String:(const char *)scan];
+ return result;
+ }
+
+ NSMutableString *result =
+ [NSMutableString stringWithCapacity:[inputStr length]];
+
+ const uint8_t kAddUnderscore = 0b10000000;
+ const uint8_t kOpMask = 0b01100000;
+ // const uint8_t kOpAsIs = 0b00000000;
+ const uint8_t kOpFirstUpper = 0b01000000;
+ const uint8_t kOpFirstLower = 0b00100000;
+ const uint8_t kOpAllUpper = 0b01100000;
+ const uint8_t kSegmentLenMask = 0b00011111;
+
+ NSInteger i = 0;
+ for (; *scan != 0; ++scan) {
+ if (*scan & kAddUnderscore) {
+ [result appendString:@"_"];
+ }
+ int segmentLen = *scan & kSegmentLenMask;
+ uint8_t decodeOp = *scan & kOpMask;
+
+ // Do op specific handling of the first character.
+ if (decodeOp == kOpFirstUpper) {
+ unichar c = [inputStr characterAtIndex:i];
+ [result appendFormat:@"%c", toupper((char)c)];
+ ++i;
+ --segmentLen;
+ } else if (decodeOp == kOpFirstLower) {
+ unichar c = [inputStr characterAtIndex:i];
+ [result appendFormat:@"%c", tolower((char)c)];
+ ++i;
+ --segmentLen;
+ }
+ // else op == kOpAsIs || op == kOpAllUpper
+
+ // Now pull over the rest of the length for this segment.
+ for (int x = 0; x < segmentLen; ++x) {
+ unichar c = [inputStr characterAtIndex:(i + x)];
+ if (decodeOp == kOpAllUpper) {
+ [result appendFormat:@"%c", toupper((char)c)];
+ } else {
+ [result appendFormat:@"%C", c];
+ }
+ }
+ i += segmentLen;
+ }
+
+ return result;
+}
+
+#pragma mark - GPBMessageSignatureProtocol
+
+// A series of selectors that are used solely to get @encoding values
+// for them by the dynamic protobuf runtime code. An object using the protocol
+// needs to be declared for the protocol to be valid at runtime.
+@interface GPBMessageSignatureProtocol : NSObject<GPBMessageSignatureProtocol>
+@end
+@implementation GPBMessageSignatureProtocol
+@end
diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h
new file mode 100644
index 00000000..1481d071
--- /dev/null
+++ b/objectivec/GPBUtilities_PackagePrivate.h
@@ -0,0 +1,426 @@
+// 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 <Foundation/Foundation.h>
+
+#import "GPBUtilities.h"
+
+#import "GPBDescriptor_PackagePrivate.h"
+
+// Macros for stringifying library symbols. These are used in the generated
+// PB descriptor classes wherever a library symbol name is represented as a
+// string. See README.google for more information.
+#define GPBStringify(S) #S
+#define GPBStringifySymbol(S) GPBStringify(S)
+
+#define GPBNSStringify(S) @#S
+#define GPBNSStringifySymbol(S) GPBNSStringify(S)
+
+// Constant to internally mark when there is no has bit.
+#define GPBNoHasBit INT32_MAX
+
+CF_EXTERN_C_BEGIN
+
+// Conversion functions for de/serializing floating point types.
+
+GPB_INLINE int64_t GPBConvertDoubleToInt64(double v) {
+ union { double f; int64_t i; } u;
+ u.f = v;
+ return u.i;
+}
+
+GPB_INLINE int32_t GPBConvertFloatToInt32(float v) {
+ union { float f; int32_t i; } u;
+ u.f = v;
+ return u.i;
+}
+
+GPB_INLINE double GPBConvertInt64ToDouble(int64_t v) {
+ union { double f; int64_t i; } u;
+ u.i = v;
+ return u.f;
+}
+
+GPB_INLINE float GPBConvertInt32ToFloat(int32_t v) {
+ union { float f; int32_t i; } u;
+ u.i = v;
+ return u.f;
+}
+
+GPB_INLINE int32_t GPBLogicalRightShift32(int32_t value, int32_t spaces) {
+ return (int32_t)((uint32_t)(value) >> spaces);
+}
+
+GPB_INLINE int64_t GPBLogicalRightShift64(int64_t value, int32_t spaces) {
+ return (int64_t)((uint64_t)(value) >> spaces);
+}
+
+// Decode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
+// into values that can be efficiently encoded with varint. (Otherwise,
+// negative values must be sign-extended to 64 bits to be varint encoded,
+// thus always taking 10 bytes on the wire.)
+GPB_INLINE int32_t GPBDecodeZigZag32(uint32_t n) {
+ return GPBLogicalRightShift32(n, 1) ^ -(n & 1);
+}
+
+// Decode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
+// into values that can be efficiently encoded with varint. (Otherwise,
+// negative values must be sign-extended to 64 bits to be varint encoded,
+// thus always taking 10 bytes on the wire.)
+GPB_INLINE int64_t GPBDecodeZigZag64(uint64_t n) {
+ return GPBLogicalRightShift64(n, 1) ^ -(n & 1);
+}
+
+// Encode a ZigZag-encoded 32-bit value. ZigZag encodes signed integers
+// into values that can be efficiently encoded with varint. (Otherwise,
+// negative values must be sign-extended to 64 bits to be varint encoded,
+// thus always taking 10 bytes on the wire.)
+GPB_INLINE uint32_t GPBEncodeZigZag32(int32_t n) {
+ // Note: the right-shift must be arithmetic
+ return (n << 1) ^ (n >> 31);
+}
+
+// Encode a ZigZag-encoded 64-bit value. ZigZag encodes signed integers
+// into values that can be efficiently encoded with varint. (Otherwise,
+// negative values must be sign-extended to 64 bits to be varint encoded,
+// thus always taking 10 bytes on the wire.)
+GPB_INLINE uint64_t GPBEncodeZigZag64(int64_t n) {
+ // Note: the right-shift must be arithmetic
+ return (n << 1) ^ (n >> 63);
+}
+
+GPB_INLINE BOOL GPBTypeIsObject(GPBType type) {
+ switch (type) {
+ case GPBTypeData:
+ case GPBTypeString:
+ case GPBTypeMessage:
+ case GPBTypeGroup:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+GPB_INLINE BOOL GPBTypeIsMessage(GPBType type) {
+ switch (type) {
+ case GPBTypeMessage:
+ case GPBTypeGroup:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+GPB_INLINE BOOL GPBTypeIsEnum(GPBType type) { return type == GPBTypeEnum; }
+
+GPB_INLINE BOOL GPBFieldTypeIsMessage(GPBFieldDescriptor *field) {
+ return GPBTypeIsMessage(field->description_->type);
+}
+
+GPB_INLINE BOOL GPBFieldTypeIsObject(GPBFieldDescriptor *field) {
+ return GPBTypeIsObject(field->description_->type);
+}
+
+GPB_INLINE BOOL GPBExtensionIsMessage(GPBExtensionDescriptor *ext) {
+ return GPBTypeIsMessage(ext->description_->type);
+}
+
+// The field is an array/map or it has an object value.
+GPB_INLINE BOOL GPBFieldStoresObject(GPBFieldDescriptor *field) {
+ GPBMessageFieldDescription *desc = field->description_;
+ if ((desc->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0) {
+ return YES;
+ }
+ return GPBTypeIsObject(desc->type);
+}
+
+BOOL GPBGetHasIvar(GPBMessage *self, int32_t index, uint32_t fieldNumber);
+void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber,
+ BOOL value);
+uint32_t GPBGetHasOneof(GPBMessage *self, int32_t index);
+
+GPB_INLINE BOOL
+GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) {
+ GPBMessageFieldDescription *fieldDesc = field->description_;
+ return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number);
+}
+GPB_INLINE void GPBSetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field,
+ BOOL value) {
+ GPBMessageFieldDescription *fieldDesc = field->description_;
+ GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, value);
+}
+
+void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
+ uint32_t fieldNumberNotToClear);
+
+//%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE)
+//%void GPBSet##NAME##IvarWithFieldInternal(GPBMessage *self,
+//% NAME$S GPBFieldDescriptor *field,
+//% NAME$S TYPE value,
+//% NAME$S GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Bool, BOOL)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetBoolIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ BOOL value,
+ GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Int32, int32_t)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetInt32IvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value,
+ GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt32, uint32_t)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetUInt32IvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint32_t value,
+ GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Int64, int64_t)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetInt64IvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int64_t value,
+ GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(UInt64, uint64_t)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetUInt64IvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ uint64_t value,
+ GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Float, float)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetFloatIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ float value,
+ GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Double, double)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetDoubleIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ double value,
+ GPBFileSyntax syntax);
+//%PDDM-EXPAND GPB_IVAR_SET_DECL(Enum, int32_t)
+// This block of code is generated, do not edit it directly.
+
+void GPBSetEnumIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ int32_t value,
+ GPBFileSyntax syntax);
+//%PDDM-EXPAND-END (8 expansions)
+
+int32_t GPBGetEnumIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ GPBFileSyntax syntax);
+
+id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
+
+void GPBSetObjectIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field, id value,
+ GPBFileSyntax syntax);
+void GPBSetRetainedObjectIvarWithFieldInternal(GPBMessage *self,
+ GPBFieldDescriptor *field,
+ id __attribute__((ns_consumed))
+ value,
+ GPBFileSyntax syntax);
+
+// GPBGetObjectIvarWithField will automatically create the field (message) if
+// it doesn't exist. GPBGetObjectIvarWithFieldNoAutocreate will return nil.
+id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
+ GPBFieldDescriptor *field);
+
+void GPBSetAutocreatedRetainedObjectIvarWithField(
+ GPBMessage *self, GPBFieldDescriptor *field,
+ id __attribute__((ns_consumed)) value);
+
+// Clears and releases the autocreated message ivar, if it's autocreated. If
+// it's not set as autocreated, this method does nothing.
+void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
+ GPBFieldDescriptor *field);
+
+// Utilities for applying various functions based on Objective C types.
+
+// A basic functor that is passed a field and a context. Returns YES
+// if the calling function should continue processing, and NO if the calling
+// function should stop processing.
+typedef BOOL (*GPBApplyFunction)(GPBFieldDescriptor *field, void *context);
+
+// Functions called for various types. See ApplyFunctionsToMessageFields.
+typedef enum {
+ GPBApplyFunctionObject,
+ GPBApplyFunctionBool,
+ GPBApplyFunctionInt32,
+ GPBApplyFunctionUInt32,
+ GPBApplyFunctionInt64,
+ GPBApplyFunctionUInt64,
+ GPBApplyFunctionFloat,
+ GPBApplyFunctionDouble,
+} GPBApplyFunctionOrder;
+
+enum {
+ // A count of the number of types in GPBApplyFunctionOrder. Separated out
+ // from the GPBApplyFunctionOrder enum to avoid warnings regarding not
+ // handling GPBApplyFunctionCount in switch statements.
+ GPBApplyFunctionCount = GPBApplyFunctionDouble + 1
+};
+
+typedef GPBApplyFunction GPBApplyFunctions[GPBApplyFunctionCount];
+
+// Functions called for various types.
+// See ApplyStrictFunctionsToMessageFields.
+// They are in the same order as the GPBTypes enum.
+typedef GPBApplyFunction GPBApplyStrictFunctions[GPBTypeCount];
+
+// A macro for easily initializing a GPBApplyFunctions struct
+// GPBApplyFunctions foo = GPBAPPLY_FUNCTIONS_INIT(Foo);
+#define GPBAPPLY_FUNCTIONS_INIT(PREFIX) \
+ { \
+ PREFIX##Object, \
+ PREFIX##Bool, \
+ PREFIX##Int32, \
+ PREFIX##UInt32, \
+ PREFIX##Int64, \
+ PREFIX##UInt64, \
+ PREFIX##Float, \
+ PREFIX##Double, \
+ }
+
+// A macro for easily initializing a GPBApplyStrictFunctions struct
+// GPBApplyStrictFunctions foo = GPBAPPLY_STRICT_FUNCTIONS_INIT(Foo);
+// These need to stay in the same order as
+// the GPBType enum.
+#define GPBAPPLY_STRICT_FUNCTIONS_INIT(PREFIX) \
+ { \
+ PREFIX##Bool, \
+ PREFIX##Fixed32, \
+ PREFIX##SFixed32, \
+ PREFIX##Float, \
+ PREFIX##Fixed64, \
+ PREFIX##SFixed64, \
+ PREFIX##Double, \
+ PREFIX##Int32, \
+ PREFIX##Int64, \
+ PREFIX##SInt32, \
+ PREFIX##SInt64, \
+ PREFIX##UInt32, \
+ PREFIX##UInt64, \
+ PREFIX##Data, \
+ PREFIX##String, \
+ PREFIX##Message, \
+ PREFIX##Group, \
+ PREFIX##Enum, \
+}
+
+// Iterates over the fields of a proto |msg| and applies the functions in
+// |functions| to them with |context|. If one of the functions in |functions|
+// returns NO, it will return immediately and not process the rest of the
+// ivars. The types in the fields are mapped so:
+// Int32, Enum, SInt32 and SFixed32 will be mapped to the int32Function,
+// UInt32 and Fixed32 will be mapped to the uint32Function,
+// Bytes, String, Message and Group will be mapped to the objectFunction,
+// etc..
+// If you require more specific mappings look at
+// GPBApplyStrictFunctionsToMessageFields.
+void GPBApplyFunctionsToMessageFields(GPBApplyFunctions *functions,
+ GPBMessage *msg, void *context);
+
+// Iterates over the fields of a proto |msg| and applies the functions in
+// |functions| to them with |context|. If one of the functions in |functions|
+// returns NO, it will return immediately and not process the rest of the
+// ivars. The types in the fields are mapped directly:
+// Int32 -> functions[GPBTypeInt32],
+// SFixed32 -> functions[GPBTypeSFixed32],
+// etc...
+// If you can use looser mappings look at GPBApplyFunctionsToMessageFields.
+void GPBApplyStrictFunctionsToMessageFields(GPBApplyStrictFunctions *functions,
+ GPBMessage *msg, void *context);
+
+// Applies the appropriate function in |functions| based on |field|.
+// Returns the value from function(name, context).
+// Throws an exception if the type is unrecognized.
+BOOL GPBApplyFunctionsBasedOnField(GPBFieldDescriptor *field,
+ GPBApplyFunctions *functions, void *context);
+
+// Returns an Objective C encoding for |selector|. |instanceSel| should be
+// YES if it's an instance selector (as opposed to a class selector).
+// |selector| must be a selector from MessageSignatureProtocol.
+const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel);
+
+// Helper for text format name encoding.
+// decodeData is the data describing the sepecial decodes.
+// key and inputString are the input that needs decoding.
+NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
+ NSString *inputString);
+
+// A series of selectors that are used solely to get @encoding values
+// for them by the dynamic protobuf runtime code. See
+// GPBMessageEncodingForSelector for details.
+@protocol GPBMessageSignatureProtocol
+@optional
+
+#define GPB_MESSAGE_SIGNATURE_ENTRY(TYPE, NAME) \
+ -(TYPE)get##NAME; \
+ -(void)set##NAME : (TYPE)value; \
+ -(TYPE)get##NAME##AtIndex : (NSUInteger)index;
+
+GPB_MESSAGE_SIGNATURE_ENTRY(BOOL, Bool)
+GPB_MESSAGE_SIGNATURE_ENTRY(uint32_t, Fixed32)
+GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, SFixed32)
+GPB_MESSAGE_SIGNATURE_ENTRY(float, Float)
+GPB_MESSAGE_SIGNATURE_ENTRY(uint64_t, Fixed64)
+GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, SFixed64)
+GPB_MESSAGE_SIGNATURE_ENTRY(double, Double)
+GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, Int32)
+GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, Int64)
+GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, SInt32)
+GPB_MESSAGE_SIGNATURE_ENTRY(int64_t, SInt64)
+GPB_MESSAGE_SIGNATURE_ENTRY(uint32_t, UInt32)
+GPB_MESSAGE_SIGNATURE_ENTRY(uint64_t, UInt64)
+GPB_MESSAGE_SIGNATURE_ENTRY(NSData *, Data)
+GPB_MESSAGE_SIGNATURE_ENTRY(NSString *, String)
+GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Message)
+GPB_MESSAGE_SIGNATURE_ENTRY(GPBMessage *, Group)
+GPB_MESSAGE_SIGNATURE_ENTRY(int32_t, Enum)
+
+#undef GPB_MESSAGE_SIGNATURE_ENTRY
+
+- (id)getArray;
+- (void)setArray:(NSArray *)array;
++ (id)getClassValue;
+@end
+
+CF_EXTERN_C_END
diff --git a/objectivec/GPBWellKnownTypes.h b/objectivec/GPBWellKnownTypes.h
new file mode 100644
index 00000000..321cdc3e
--- /dev/null
+++ b/objectivec/GPBWellKnownTypes.h
@@ -0,0 +1,48 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/Timestamp.pbobjc.h"
+#import "google/protobuf/Duration.pbobjc.h"
+
+// Extension to GPBTimestamp to work with standard Foundation time/date types.
+@interface GPBTimestamp (GBPWellKnownTypes)
+@property(nonatomic, readwrite, strong) NSDate *date;
+@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970;
+- (instancetype)initWithDate:(NSDate *)date;
+- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970;
+@end
+
+// Extension to GPBDuration to work with standard Foundation time type.
+@interface GPBDuration (GBPWellKnownTypes)
+@property(nonatomic, readwrite) NSTimeInterval timeIntervalSince1970;
+- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970;
+@end
diff --git a/objectivec/GPBWellKnownTypes.m b/objectivec/GPBWellKnownTypes.m
new file mode 100644
index 00000000..fe02f5de
--- /dev/null
+++ b/objectivec/GPBWellKnownTypes.m
@@ -0,0 +1,117 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+// Importing sources here to force the linker to include our category methods in
+// the static library. If these were compiled separately, the category methods
+// below would be stripped by the linker.
+
+#import "google/protobuf/Timestamp.pbobjc.m"
+#import "google/protobuf/Duration.pbobjc.m"
+#import "GPBWellKnownTypes.h"
+
+static NSTimeInterval TimeIntervalSince1970FromSecondsAndNanos(int64_t seconds,
+ int32_t nanos) {
+ return seconds + (NSTimeInterval)nanos / 1e9;
+}
+
+static int32_t SecondsAndNanosFromTimeIntervalSince1970(NSTimeInterval time,
+ int64_t *outSeconds) {
+ NSTimeInterval seconds;
+ NSTimeInterval nanos = modf(time, &seconds);
+ nanos *= 1e9;
+ *outSeconds = (int64_t)seconds;
+ return (int32_t)nanos;
+}
+
+@implementation GPBTimestamp (GBPWellKnownTypes)
+
+- (instancetype)initWithDate:(NSDate *)date {
+ return [self initWithTimeIntervalSince1970:date.timeIntervalSince1970];
+}
+
+- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
+ if ((self = [super init])) {
+ int64_t seconds;
+ int32_t nanos = SecondsAndNanosFromTimeIntervalSince1970(
+ timeIntervalSince1970, &seconds);
+ self.seconds = seconds;
+ self.nanos = nanos;
+ }
+ return self;
+}
+
+- (NSDate *)date {
+ return [NSDate dateWithTimeIntervalSince1970:self.timeIntervalSince1970];
+}
+
+- (void)setDate:(NSDate *)date {
+ self.timeIntervalSince1970 = date.timeIntervalSince1970;
+}
+
+- (NSTimeInterval)timeIntervalSince1970 {
+ return TimeIntervalSince1970FromSecondsAndNanos(self.seconds, self.nanos);
+}
+
+- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
+ int64_t seconds;
+ int32_t nanos =
+ SecondsAndNanosFromTimeIntervalSince1970(timeIntervalSince1970, &seconds);
+ self.seconds = seconds;
+ self.nanos = nanos;
+}
+
+@end
+
+@implementation GPBDuration (GBPWellKnownTypes)
+
+- (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
+ if ((self = [super init])) {
+ int64_t seconds;
+ int32_t nanos = SecondsAndNanosFromTimeIntervalSince1970(
+ timeIntervalSince1970, &seconds);
+ self.seconds = seconds;
+ self.nanos = nanos;
+ }
+ return self;
+}
+
+- (NSTimeInterval)timeIntervalSince1970 {
+ return TimeIntervalSince1970FromSecondsAndNanos(self.seconds, self.nanos);
+}
+
+- (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
+ int64_t seconds;
+ int32_t nanos =
+ SecondsAndNanosFromTimeIntervalSince1970(timeIntervalSince1970, &seconds);
+ self.seconds = seconds;
+ self.nanos = nanos;
+}
+
+@end
diff --git a/objectivec/GPBWireFormat.h b/objectivec/GPBWireFormat.h
new file mode 100644
index 00000000..55f2edfc
--- /dev/null
+++ b/objectivec/GPBWireFormat.h
@@ -0,0 +1,68 @@
+// 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 "GPBTypes.h"
+
+CF_EXTERN_C_BEGIN
+
+typedef enum {
+ GPBWireFormatVarint = 0,
+ GPBWireFormatFixed64 = 1,
+ GPBWireFormatLengthDelimited = 2,
+ GPBWireFormatStartGroup = 3,
+ GPBWireFormatEndGroup = 4,
+ GPBWireFormatFixed32 = 5,
+} GPBWireFormat;
+
+enum {
+ GPBWireFormatMessageSetItem = 1,
+ GPBWireFormatMessageSetTypeId = 2,
+ GPBWireFormatMessageSetMessage = 3
+};
+
+uint32_t GPBWireFormatMakeTag(uint32_t fieldNumber, GPBWireFormat wireType)
+ __attribute__((const));
+GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) __attribute__((const));
+uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) __attribute__((const));
+
+GPBWireFormat GPBWireFormatForType(GPBType type, BOOL isPacked)
+ __attribute__((const));
+
+#define GPBWireFormatMessageSetItemTag \
+ (GPBWireFormatMakeTag(GPBWireFormatMessageSetItem, GPBWireFormatStartGroup))
+#define GPBWireFormatMessageSetItemEndTag \
+ (GPBWireFormatMakeTag(GPBWireFormatMessageSetItem, GPBWireFormatEndGroup))
+#define GPBWireFormatMessageSetTypeIdTag \
+ (GPBWireFormatMakeTag(GPBWireFormatMessageSetTypeId, GPBWireFormatVarint))
+#define GPBWireFormatMessageSetMessageTag \
+ (GPBWireFormatMakeTag(GPBWireFormatMessageSetMessage, \
+ GPBWireFormatLengthDelimited))
+
+CF_EXTERN_C_END
diff --git a/objectivec/GPBWireFormat.m b/objectivec/GPBWireFormat.m
new file mode 100644
index 00000000..7435221f
--- /dev/null
+++ b/objectivec/GPBWireFormat.m
@@ -0,0 +1,78 @@
+// 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 "GPBWireFormat.h"
+
+#import "GPBUtilities_PackagePrivate.h"
+
+enum {
+ GPBWireFormatTagTypeBits = 3,
+ GPBWireFormatTagTypeMask = 7 /* = (1 << GPBWireFormatTagTypeBits) - 1 */,
+};
+
+uint32_t GPBWireFormatMakeTag(uint32_t fieldNumber, GPBWireFormat wireType) {
+ return (fieldNumber << GPBWireFormatTagTypeBits) | wireType;
+}
+
+GPBWireFormat GPBWireFormatGetTagWireType(uint32_t tag) {
+ return (GPBWireFormat)(tag & GPBWireFormatTagTypeMask);
+}
+
+uint32_t GPBWireFormatGetTagFieldNumber(uint32_t tag) {
+ return GPBLogicalRightShift32(tag, GPBWireFormatTagTypeBits);
+}
+
+GPBWireFormat GPBWireFormatForType(GPBType type, BOOL isPacked) {
+ if (isPacked) {
+ return GPBWireFormatLengthDelimited;
+ }
+
+ static const GPBWireFormat format[GPBTypeCount] = {
+ GPBWireFormatVarint, // GPBTypeBool
+ GPBWireFormatFixed32, // GPBTypeFixed32
+ GPBWireFormatFixed32, // GPBTypeSFixed32
+ GPBWireFormatFixed32, // GPBTypeFloat
+ GPBWireFormatFixed64, // GPBTypeFixed64
+ GPBWireFormatFixed64, // GPBTypeSFixed64
+ GPBWireFormatFixed64, // GPBTypeDouble
+ GPBWireFormatVarint, // GPBTypeInt32
+ GPBWireFormatVarint, // GPBTypeInt64
+ GPBWireFormatVarint, // GPBTypeSInt32
+ GPBWireFormatVarint, // GPBTypeSInt64
+ GPBWireFormatVarint, // GPBTypeUInt32
+ GPBWireFormatVarint, // GPBTypeUInt64
+ GPBWireFormatLengthDelimited, // GPBTypeBytes
+ GPBWireFormatLengthDelimited, // GPBTypeString
+ GPBWireFormatLengthDelimited, // GPBTypeMessage
+ GPBWireFormatStartGroup, // GPBTypeGroup
+ GPBWireFormatVarint // GPBTypeEnum
+ };
+ return format[type];
+}
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..46416043
--- /dev/null
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
@@ -0,0 +1,919 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 47;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 8BD3981414BE4AE70081D629 /* Compile_Protos */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 8BD3981714BE4AE70081D629 /* Build configuration list for PBXAggregateTarget "Compile_Protos" */;
+ buildPhases = (
+ 8BD3981814BE4AF30081D629 /* ShellScript */,
+ );
+ dependencies = (
+ );
+ name = Compile_Protos;
+ productName = Compile_Protos;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */; };
+ 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */; };
+ 7461B5360F94FB4600A0C422 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */; };
+ 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */; };
+ 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */; };
+ 7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBField.m */; };
+ 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4BF0F94F99000A0C422 /* GPBMessage.m */; };
+ 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */; };
+ 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E60F94F99000A0C422 /* GPBUtilities.m */; };
+ 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */; };
+ 8B210CCE159383D60032D72D /* golden_message in Resources */ = {isa = PBXBuildFile; fileRef = 8B210CCD159383D60032D72D /* golden_message */; };
+ 8B210CD0159386920032D72D /* golden_packed_fields_message in Resources */ = {isa = PBXBuildFile; fileRef = 8B210CCF159386920032D72D /* golden_packed_fields_message */; };
+ 8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248BA1A8C256A00BC1EC6 /* GPBSwiftTests.swift */; };
+ 8B4248D21A927E1500BC1EC6 /* GPBWellKnownTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248D01A927E1500BC1EC6 /* GPBWellKnownTypes.m */; };
+ 8B4248DC1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248DB1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m */; };
+ 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B79657914992E3E002FFBFC /* GPBRootObject.m */; };
+ 8B79657D14992E3F002FFBFC /* GPBRootObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B79657914992E3E002FFBFC /* GPBRootObject.m */; };
+ 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 */; };
+ 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */; };
+ 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */; };
+ 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */; };
+ 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */; };
+ 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; };
+ 8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */; };
+ 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; };
+ 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC2B1A8D444600FCC765 /* GPBArray.m */; };
+ F401DC331A8E5C0200FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */; };
+ F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F41C175C1833D3310064ED4D /* GPBPerfTests.m */; };
+ F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */; };
+ F4353D231ABB1537005A6198 /* GPBDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D211ABB1537005A6198 /* GPBDictionary.m */; };
+ F4353D341AC06F10005A6198 /* GPBDictionaryTests+Bool.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D2D1AC06F10005A6198 /* GPBDictionaryTests+Bool.m */; };
+ F4353D351AC06F10005A6198 /* GPBDictionaryTests+Int32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D2E1AC06F10005A6198 /* GPBDictionaryTests+Int32.m */; };
+ F4353D361AC06F10005A6198 /* GPBDictionaryTests+Int64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D2F1AC06F10005A6198 /* GPBDictionaryTests+Int64.m */; };
+ F4353D371AC06F10005A6198 /* GPBDictionaryTests+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D301AC06F10005A6198 /* GPBDictionaryTests+String.m */; };
+ F4353D381AC06F10005A6198 /* GPBDictionaryTests+UInt32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D311AC06F10005A6198 /* GPBDictionaryTests+UInt32.m */; };
+ F4353D391AC06F10005A6198 /* GPBDictionaryTests+UInt64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */; };
+ F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */; };
+ F4487C4D1A9F8E0200531423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ F4487C521A9F8E4D00531423 /* GPBProtocolBuffers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */; };
+ F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */; };
+ F4487C7F1AAF62CD00531423 /* GPBMessageTests+Serialization.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */; };
+ F4487C831AAF6AB300531423 /* GPBMessageTests+Merge.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */; };
+ F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionField.m */; };
+ F45E57C71AE6DC6A000B7D99 /* text_format_map_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7461B52D0F94FAF800A0C422;
+ remoteInfo = ProtocolBuffers;
+ };
+ 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8BD3981414BE4AE70081D629;
+ remoteInfo = Compile_Protos;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBConcurrencyTests.m; sourceTree = "<group>"; };
+ 51457B5F18D0B7AF00CCC606 /* GPBCodedInputStream_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBCodedInputStream_PackagePrivate.h; sourceTree = "<group>"; };
+ 515B840C18B7DEE30031753B /* GPBDescriptor_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDescriptor_PackagePrivate.h; sourceTree = "<group>"; };
+ 5196A06918CE16B000B759E2 /* GPBMessage_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBMessage_PackagePrivate.h; sourceTree = "<group>"; };
+ 7401C1A90F950347006D8281 /* UnitTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "UnitTests-Info.plist"; sourceTree = "<group>"; };
+ 7461B48D0F94F99000A0C422 /* GPBBootstrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBBootstrap.h; sourceTree = "<group>"; };
+ 7461B48E0F94F99000A0C422 /* GPBCodedInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBCodedInputStream.h; sourceTree = "<group>"; };
+ 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GPBCodedInputStream.m; sourceTree = "<group>"; };
+ 7461B4900F94F99000A0C422 /* GPBCodedOutputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBCodedOutputStream.h; sourceTree = "<group>"; };
+ 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOutputStream.m; sourceTree = "<group>"; };
+ 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionRegistry.h; sourceTree = "<group>"; };
+ 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionRegistry.m; sourceTree = "<group>"; };
+ 7461B4AE0F94F99000A0C422 /* GPBField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBField.h; sourceTree = "<group>"; };
+ 7461B4AF0F94F99000A0C422 /* GPBField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBField.m; sourceTree = "<group>"; };
+ 7461B4BE0F94F99000A0C422 /* GPBMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBMessage.h; sourceTree = "<group>"; };
+ 7461B4BF0F94F99000A0C422 /* GPBMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessage.m; sourceTree = "<group>"; };
+ 7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers.h; sourceTree = "<group>"; };
+ 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet.h; sourceTree = "<group>"; };
+ 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSet.m; sourceTree = "<group>"; };
+ 7461B4E50F94F99000A0C422 /* GPBUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUtilities.h; sourceTree = "<group>"; };
+ 7461B4E60F94F99000A0C422 /* GPBUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilities.m; sourceTree = "<group>"; };
+ 7461B4E70F94F99000A0C422 /* GPBWireFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWireFormat.h; sourceTree = "<group>"; };
+ 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormat.m; sourceTree = "<group>"; };
+ 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libProtocolBuffers.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedInputStreamTests.m; sourceTree = "<group>"; };
+ 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOuputStreamTests.m; sourceTree = "<group>"; };
+ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessageTests.m; sourceTree = "<group>"; };
+ 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTestUtilities.h; sourceTree = "<group>"; };
+ 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTestUtilities.m; sourceTree = "<group>"; };
+ 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSetTest.m; sourceTree = "<group>"; };
+ 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilitiesTests.m; sourceTree = "<group>"; };
+ 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormatTests.m; sourceTree = "<group>"; };
+ 748F0CAF0FD70602000858A9 /* GPBExtensionField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField.h; sourceTree = "<group>"; };
+ 8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = "<group>"; };
+ 8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Filter1.txt; sourceTree = "<group>"; };
+ 8B20A9A916F1BC0600BE3EAD /* unittest_filter.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_filter.proto; sourceTree = "<group>"; };
+ 8B210CCD159383D60032D72D /* golden_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_message; sourceTree = "<group>"; };
+ 8B210CCF159386920032D72D /* golden_packed_fields_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_packed_fields_message; sourceTree = "<group>"; };
+ 8B4248B81A8C254000BC1EC6 /* protobuf */ = {isa = PBXFileReference; lastKnownFileType = text; name = protobuf; path = ../../Intermediates/ProtocolBuffers_OSX.build/DerivedSources/protos/google/protobuf; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8B4248B91A8C256900BC1EC6 /* UnitTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnitTests-Bridging-Header.h"; sourceTree = "<group>"; };
+ 8B4248BA1A8C256A00BC1EC6 /* GPBSwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPBSwiftTests.swift; sourceTree = "<group>"; };
+ 8B4248CF1A927E1500BC1EC6 /* GPBWellKnownTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWellKnownTypes.h; sourceTree = "<group>"; };
+ 8B4248D01A927E1500BC1EC6 /* GPBWellKnownTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypes.m; sourceTree = "<group>"; };
+ 8B4248D31A92826400BC1EC6 /* Duration.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Duration.pbobjc.h; path = google/protobuf/Duration.pbobjc.h; sourceTree = "<group>"; };
+ 8B4248D41A92826400BC1EC6 /* Duration.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Duration.pbobjc.m; path = google/protobuf/Duration.pbobjc.m; sourceTree = "<group>"; };
+ 8B4248D51A92826400BC1EC6 /* Timestamp.pbobjc.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = Timestamp.pbobjc.h; path = google/protobuf/Timestamp.pbobjc.h; sourceTree = "<group>"; };
+ 8B4248D61A92826400BC1EC6 /* Timestamp.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Timestamp.pbobjc.m; path = google/protobuf/Timestamp.pbobjc.m; sourceTree = "<group>"; };
+ 8B4248DB1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypesTest.m; sourceTree = "<group>"; };
+ 8B42494B1A92A16600BC1EC6 /* descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = descriptor.proto; path = ../src/google/protobuf/descriptor.proto; sourceTree = "<group>"; };
+ 8B42494C1A92A16600BC1EC6 /* duration.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = duration.proto; path = ../src/google/protobuf/duration.proto; sourceTree = "<group>"; };
+ 8B42494D1A92A16600BC1EC6 /* timestamp.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = timestamp.proto; path = ../src/google/protobuf/timestamp.proto; sourceTree = "<group>"; };
+ 8B54585814DCC34E003D7338 /* Descriptor.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Descriptor.pbobjc.h; path = google/protobuf/Descriptor.pbobjc.h; sourceTree = SOURCE_ROOT; };
+ 8B79657814992E3E002FFBFC /* GPBRootObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBRootObject.h; sourceTree = "<group>"; };
+ 8B79657914992E3E002FFBFC /* GPBRootObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBRootObject.m; sourceTree = "<group>"; };
+ 8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_custom_options.proto; path = ../../src/google/protobuf/unittest_custom_options.proto; sourceTree = "<group>"; };
+ 8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_embed_optimize_for.proto; path = ../../src/google/protobuf/unittest_embed_optimize_for.proto; sourceTree = "<group>"; };
+ 8B7E6A7614893DBA00F8884A /* unittest_empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_empty.proto; path = ../../src/google/protobuf/unittest_empty.proto; sourceTree = "<group>"; };
+ 8B7E6A7814893DBB00F8884A /* unittest_import.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_import.proto; path = ../../src/google/protobuf/unittest_import.proto; sourceTree = "<group>"; };
+ 8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_mset.proto; path = ../../src/google/protobuf/unittest_mset.proto; sourceTree = "<group>"; };
+ 8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_no_generic_services.proto; path = ../../src/google/protobuf/unittest_no_generic_services.proto; sourceTree = "<group>"; };
+ 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_optimize_for.proto; path = ../../src/google/protobuf/unittest_optimize_for.proto; sourceTree = "<group>"; };
+ 8B7E6A7E14893DBC00F8884A /* unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest.proto; path = ../../src/google/protobuf/unittest.proto; sourceTree = "<group>"; };
+ 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; };
+ 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBFilteredMessageTests.m; sourceTree = "<group>"; };
+ 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = "<group>"; };
+ 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = "<group>"; };
+ 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = "<group>"; };
+ 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Descriptor.pbobjc.m; path = google/protobuf/Descriptor.pbobjc.m; sourceTree = SOURCE_ROOT; };
+ 8BEB5AE01498033E0078BF9D /* GPBTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBTypes.h; sourceTree = "<group>"; };
+ F401DC2A1A8D444600FCC765 /* GPBArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBArray.h; sourceTree = "<group>"; };
+ F401DC2B1A8D444600FCC765 /* GPBArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArray.m; sourceTree = "<group>"; };
+ F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = "<group>"; };
+ F41C175C1833D3310064ED4D /* GPBPerfTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBPerfTests.m; sourceTree = "<group>"; };
+ F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptorTests.m; sourceTree = "<group>"; };
+ F4353D201ABB1537005A6198 /* GPBDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDictionary.h; sourceTree = "<group>"; };
+ F4353D211ABB1537005A6198 /* GPBDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionary.m; sourceTree = "<group>"; };
+ F4353D2C1AC06F10005A6198 /* GPBDictionaryTests.pddm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = GPBDictionaryTests.pddm; sourceTree = "<group>"; };
+ F4353D2D1AC06F10005A6198 /* GPBDictionaryTests+Bool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+Bool.m"; sourceTree = "<group>"; };
+ F4353D2E1AC06F10005A6198 /* GPBDictionaryTests+Int32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+Int32.m"; sourceTree = "<group>"; };
+ F4353D2F1AC06F10005A6198 /* GPBDictionaryTests+Int64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+Int64.m"; sourceTree = "<group>"; };
+ F4353D301AC06F10005A6198 /* GPBDictionaryTests+String.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+String.m"; sourceTree = "<group>"; };
+ F4353D311AC06F10005A6198 /* GPBDictionaryTests+UInt32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt32.m"; sourceTree = "<group>"; };
+ F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt64.m"; sourceTree = "<group>"; };
+ F43725911AC9832D004DCAFB /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDictionary_PackagePrivate.h; sourceTree = "<group>"; };
+ F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_unittest_data.txt; sourceTree = "<group>"; };
+ F4411BE71AF12FD700324B4A /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBArray_PackagePrivate.h; sourceTree = "<group>"; };
+ F4487C511A9F8E0200531423 /* libTestSingleSourceBuild.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestSingleSourceBuild.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Runtime.m"; sourceTree = "<group>"; };
+ F4487C781AADFB3100531423 /* unittest_runtime_proto2.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_runtime_proto2.proto; sourceTree = "<group>"; };
+ F4487C791AADFB3200531423 /* unittest_runtime_proto3.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_runtime_proto3.proto; sourceTree = "<group>"; };
+ F4487C7C1AAE06AC00531423 /* GPBUtilities_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUtilities_PackagePrivate.h; sourceTree = "<group>"; };
+ F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Serialization.m"; sourceTree = "<group>"; };
+ F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Merge.m"; sourceTree = "<group>"; };
+ F44B25D81A729803005CCF68 /* Filter2.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Filter2.txt; sourceTree = "<group>"; };
+ F451D3F51A8AAE8700B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers_RuntimeSupport.h; sourceTree = "<group>"; };
+ F45C69CB16DFD08D0081955B /* GPBExtensionField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionField.m; sourceTree = "<group>"; };
+ F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_map_unittest_data.txt; sourceTree = "<group>"; };
+ F4AC9E1D1A8BEB3500BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = "<group>"; };
+ F4B6B8AF1A9CC98000892426 /* GPBField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBField_PackagePrivate.h; sourceTree = "<group>"; };
+ F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = "<group>"; };
+ F4B6B8B61A9CD1DE00892426 /* GPBExtensionField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField_PackagePrivate.h; sourceTree = "<group>"; };
+ F4B6B8B71A9CD1DE00892426 /* GPBExtensionRegistry_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionRegistry_PackagePrivate.h; sourceTree = "<group>"; };
+ F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = "<group>"; };
+ F4B6B8B91A9D338B00892426 /* unittest_name_mangling.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_name_mangling.proto; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 7461B52C0F94FAF800A0C422 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7461B5360F94FB4600A0C422 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8BBEA4A3147C727100C4ADB7 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */,
+ 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F4487C4C1A9F8E0200531423 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F4487C4D1A9F8E0200531423 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 080E96DDFE201D6D7F000001 /* Core Source */ = {
+ isa = PBXGroup;
+ children = (
+ 7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */,
+ F451D3F51A8AAE8700B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */,
+ 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */,
+ 7461B3C50F94F84100A0C422 /* Extensions */,
+ 7461B4850F94F96600A0C422 /* Fields */,
+ 7461B4860F94F96B00A0C422 /* IO */,
+ 7461B5150F94FA7300A0C422 /* Messages */,
+ 8BCF334414ED727300BC5317 /* Support */,
+ 29B97315FDCFA39411CA2CEA /* Generated */,
+ );
+ name = "Core Source";
+ sourceTree = "<group>";
+ };
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */,
+ 8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */,
+ F4487C511A9F8E0200531423 /* libTestSingleSourceBuild.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
+ isa = PBXGroup;
+ children = (
+ 080E96DDFE201D6D7F000001 /* Core Source */,
+ 7461B6940F94FDDD00A0C422 /* Tests */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ );
+ name = CustomTemplate;
+ sourceTree = "<group>";
+ };
+ 29B97315FDCFA39411CA2CEA /* Generated */ = {
+ isa = PBXGroup;
+ children = (
+ 8B42494B1A92A16600BC1EC6 /* descriptor.proto */,
+ 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */,
+ 8B54585814DCC34E003D7338 /* Descriptor.pbobjc.h */,
+ 8B42494C1A92A16600BC1EC6 /* duration.proto */,
+ 8B4248D31A92826400BC1EC6 /* Duration.pbobjc.h */,
+ 8B4248D41A92826400BC1EC6 /* Duration.pbobjc.m */,
+ 8B42494D1A92A16600BC1EC6 /* timestamp.proto */,
+ 8B4248D51A92826400BC1EC6 /* Timestamp.pbobjc.h */,
+ 8B4248D61A92826400BC1EC6 /* Timestamp.pbobjc.m */,
+ );
+ name = Generated;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 1D30AB110D05D00D00671497 /* Foundation.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 7461B3C50F94F84100A0C422 /* Extensions */ = {
+ isa = PBXGroup;
+ children = (
+ F4B6B8B61A9CD1DE00892426 /* GPBExtensionField_PackagePrivate.h */,
+ 748F0CAF0FD70602000858A9 /* GPBExtensionField.h */,
+ F45C69CB16DFD08D0081955B /* GPBExtensionField.m */,
+ F4B6B8B71A9CD1DE00892426 /* GPBExtensionRegistry_PackagePrivate.h */,
+ 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */,
+ 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */,
+ F4B6B8B81A9CD1DE00892426 /* GPBRootObject_PackagePrivate.h */,
+ 8B79657814992E3E002FFBFC /* GPBRootObject.h */,
+ 8B79657914992E3E002FFBFC /* GPBRootObject.m */,
+ );
+ name = Extensions;
+ sourceTree = "<group>";
+ };
+ 7461B4850F94F96600A0C422 /* Fields */ = {
+ isa = PBXGroup;
+ children = (
+ F4B6B8AF1A9CC98000892426 /* GPBField_PackagePrivate.h */,
+ 7461B4AE0F94F99000A0C422 /* GPBField.h */,
+ 7461B4AF0F94F99000A0C422 /* GPBField.m */,
+ F4B6B8B21A9CCBDA00892426 /* GPBUnknownFieldSet_PackagePrivate.h */,
+ 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */,
+ 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */,
+ );
+ name = Fields;
+ sourceTree = "<group>";
+ };
+ 7461B4860F94F96B00A0C422 /* IO */ = {
+ isa = PBXGroup;
+ children = (
+ 7461B48E0F94F99000A0C422 /* GPBCodedInputStream.h */,
+ 51457B5F18D0B7AF00CCC606 /* GPBCodedInputStream_PackagePrivate.h */,
+ 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */,
+ 7461B4900F94F99000A0C422 /* GPBCodedOutputStream.h */,
+ 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */,
+ 7461B4E70F94F99000A0C422 /* GPBWireFormat.h */,
+ 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */,
+ );
+ name = IO;
+ sourceTree = "<group>";
+ };
+ 7461B5150F94FA7300A0C422 /* Messages */ = {
+ isa = PBXGroup;
+ children = (
+ 515B840C18B7DEE30031753B /* GPBDescriptor_PackagePrivate.h */,
+ 8B96157214C8B06000A2AC0B /* GPBDescriptor.h */,
+ 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */,
+ 7461B4BE0F94F99000A0C422 /* GPBMessage.h */,
+ 5196A06918CE16B000B759E2 /* GPBMessage_PackagePrivate.h */,
+ 7461B4BF0F94F99000A0C422 /* GPBMessage.m */,
+ );
+ name = Messages;
+ sourceTree = "<group>";
+ };
+ 7461B6940F94FDDD00A0C422 /* Tests */ = {
+ isa = PBXGroup;
+ children = (
+ 8B4248B81A8C254000BC1EC6 /* protobuf */,
+ 8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */,
+ F44B25D81A729803005CCF68 /* Filter2.txt */,
+ 8B210CCD159383D60032D72D /* golden_message */,
+ 8B210CCF159386920032D72D /* golden_packed_fields_message */,
+ 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */,
+ F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */,
+ 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */,
+ 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */,
+ 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */,
+ F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */,
+ F4353D2C1AC06F10005A6198 /* GPBDictionaryTests.pddm */,
+ F4353D2D1AC06F10005A6198 /* GPBDictionaryTests+Bool.m */,
+ F4353D2E1AC06F10005A6198 /* GPBDictionaryTests+Int32.m */,
+ F4353D2F1AC06F10005A6198 /* GPBDictionaryTests+Int64.m */,
+ F4353D301AC06F10005A6198 /* GPBDictionaryTests+String.m */,
+ F4353D311AC06F10005A6198 /* GPBDictionaryTests+UInt32.m */,
+ F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */,
+ 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */,
+ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */,
+ F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */,
+ F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */,
+ F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */,
+ F41C175C1833D3310064ED4D /* GPBPerfTests.m */,
+ 8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */,
+ 8B4248BA1A8C256A00BC1EC6 /* GPBSwiftTests.swift */,
+ 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */,
+ 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */,
+ 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */,
+ 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */,
+ 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */,
+ 8B4248DB1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m */,
+ 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */,
+ F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */,
+ F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */,
+ 8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */,
+ F4AC9E1D1A8BEB3500BD6E83 /* unittest_cycle.proto */,
+ 8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */,
+ 8B7E6A7614893DBA00F8884A /* unittest_empty.proto */,
+ 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */,
+ 8B20A9A916F1BC0600BE3EAD /* unittest_filter.proto */,
+ 8B7E6A7814893DBB00F8884A /* unittest_import.proto */,
+ 8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */,
+ 8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */,
+ F4B6B8B91A9D338B00892426 /* unittest_name_mangling.proto */,
+ 8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */,
+ 8B09AAF614B663A7007B4184 /* unittest_objc.proto */,
+ 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */,
+ F4487C781AADFB3100531423 /* unittest_runtime_proto2.proto */,
+ F4487C791AADFB3200531423 /* unittest_runtime_proto3.proto */,
+ 8B7E6A7E14893DBC00F8884A /* unittest.proto */,
+ 8B4248B91A8C256900BC1EC6 /* UnitTests-Bridging-Header.h */,
+ 7401C1A90F950347006D8281 /* UnitTests-Info.plist */,
+ );
+ path = Tests;
+ sourceTree = "<group>";
+ };
+ 8BCF334414ED727300BC5317 /* Support */ = {
+ isa = PBXGroup;
+ children = (
+ F4411BE71AF12FD700324B4A /* GPBArray_PackagePrivate.h */,
+ F401DC2A1A8D444600FCC765 /* GPBArray.h */,
+ F401DC2B1A8D444600FCC765 /* GPBArray.m */,
+ 7461B48D0F94F99000A0C422 /* GPBBootstrap.h */,
+ F43725911AC9832D004DCAFB /* GPBDictionary_PackagePrivate.h */,
+ F4353D201ABB1537005A6198 /* GPBDictionary.h */,
+ F4353D211ABB1537005A6198 /* GPBDictionary.m */,
+ 8BEB5AE01498033E0078BF9D /* GPBTypes.h */,
+ F4487C7C1AAE06AC00531423 /* GPBUtilities_PackagePrivate.h */,
+ 7461B4E50F94F99000A0C422 /* GPBUtilities.h */,
+ 7461B4E60F94F99000A0C422 /* GPBUtilities.m */,
+ 8B4248CF1A927E1500BC1EC6 /* GPBWellKnownTypes.h */,
+ 8B4248D01A927E1500BC1EC6 /* GPBWellKnownTypes.m */,
+ );
+ name = Support;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 7461B52A0F94FAF800A0C422 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F4487C391A9F8E0200531423 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 7461B5330F94FAFD00A0C422 /* Build configuration list for PBXNativeTarget "ProtocolBuffers" */;
+ buildPhases = (
+ 7461B52A0F94FAF800A0C422 /* Headers */,
+ 7461B52B0F94FAF800A0C422 /* Sources */,
+ 7461B52C0F94FAF800A0C422 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ProtocolBuffers;
+ productName = "ProtocolBuffers-iPhoneDevice";
+ productReference = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ 8BBEA4A5147C727100C4ADB7 /* UnitTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8BBEA4BA147C728600C4ADB7 /* Build configuration list for PBXNativeTarget "UnitTests" */;
+ buildPhases = (
+ F4B62A781AF91F6000AFCEDC /* Script: Check Runtime Stamps */,
+ 8BBEA4A1147C727100C4ADB7 /* Resources */,
+ 8BBEA4A2147C727100C4ADB7 /* Sources */,
+ 8BBEA4A3147C727100C4ADB7 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */,
+ 8BD3982114BE59EB0081D629 /* PBXTargetDependency */,
+ );
+ name = UnitTests;
+ productName = UnitTests;
+ productReference = 8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ F4487C381A9F8E0200531423 /* TestSingleSourceBuild */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F4487C4E1A9F8E0200531423 /* Build configuration list for PBXNativeTarget "TestSingleSourceBuild" */;
+ buildPhases = (
+ F4487C391A9F8E0200531423 /* Headers */,
+ F4487C3D1A9F8E0200531423 /* Sources */,
+ F4487C4C1A9F8E0200531423 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = TestSingleSourceBuild;
+ productName = "ProtocolBuffers-iPhoneDevice";
+ productReference = F4487C511A9F8E0200531423 /* libTestSingleSourceBuild.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastTestingUpgradeCheck = 0600;
+ LastUpgradeCheck = 0620;
+ TargetAttributes = {
+ 8BBEA4A5147C727100C4ADB7 = {
+ TestTargetID = 8B9A5EA41831993600A9D33B;
+ };
+ };
+ };
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_OSX" */;
+ compatibilityVersion = "Xcode 6.3";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */,
+ 8BBEA4A5147C727100C4ADB7 /* UnitTests */,
+ 8BD3981414BE4AE70081D629 /* Compile_Protos */,
+ F4487C381A9F8E0200531423 /* TestSingleSourceBuild */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8BBEA4A1147C727100C4ADB7 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8B210CCE159383D60032D72D /* golden_message in Resources */,
+ F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */,
+ 8B210CD0159386920032D72D /* golden_packed_fields_message in Resources */,
+ F45E57C71AE6DC6A000B7D99 /* text_format_map_unittest_data.txt in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 8BD3981814BE4AF30081D629 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/../src/google/protobuf/unittest_custom_options.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_embed_optimize_for.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_empty.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_enormous_descriptor.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_import_lite.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_import.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_lite_imports_nonlite.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_lite.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_mset.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_no_generic_services.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest.proto",
+ "$(SRCROOT)/Tests/unittest_objc.proto",
+ "$(SRCROOT)/../src/.libs/libprotoc.10.dylib",
+ "$(SRCROOT)/../src/google/protobuf/unittest_import_public_lite.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_import_public.proto",
+ "$(SRCROOT)/Tests/unittest_filter.proto",
+ "$(SRCROOT)/../src/.libs/libprotobuf.10.dylib",
+ "$(SRCROOT)/../src/.libs/protoc",
+ "$(SRCROOT)/Tests/Filter1.txt",
+ "$(SRCROOT)/Tests/Filter2.txt",
+ "$(SRCROOT)/Tests/unittest_cycle.proto",
+ "$(SRCROOT)/Tests/unittest_name_mangling.proto",
+ "$(SRCROOT)/Tests/unittest_runtime_proto2.proto",
+ "$(SRCROOT)/Tests/unittest_runtime_proto3.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_drop_unknown_fields.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_preserve_unknown_enum.proto",
+ "$(SRCROOT)/../src/google/protobuf/map_lite_unittest.proto",
+ "$(SRCROOT)/../src/google/protobuf/map_proto2_unittest.proto",
+ "$(SRCROOT)/../src/google/protobuf/map_unittest.proto",
+ );
+ outputPaths = (
+ "$(PROJECT_DERIVED_FILE_DIR)/protos/google/protobuf/Unittest.pbobjc.h",
+ "$(PROJECT_DERIVED_FILE_DIR)/protos/google/protobuf/Unittest.pbobjc.m",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "set -eu\nmkdir -p \"${PROJECT_DERIVED_FILE_DIR}/protos\"\nexport PATH=\"${PATH}:.\"\ncd \"${SRCROOT}\"/../src\n\nPROTOC=./protoc\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_custom_options.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_enormous_descriptor.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_embed_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_empty.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_mset.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_no_generic_services.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_drop_unknown_fields.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_preserve_unknown_enum.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_lite_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_proto2_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_unittest.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_objc.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_cycle.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_name_mangling.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto2.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto3.proto\n\nexport GPB_CLASSLIST_PATH=\"${PROJECT_DERIVED_FILE_DIR}/ClassList.txt\"\nexport GPB_OBJC_CLASS_WHITELIST_PATHS=\"${SRCROOT}/Tests/Filter1.txt;${SRCROOT}/Tests/Filter2.txt\"\n\nif [ -e ${GPB_CLASSLIST_PATH} ]; then\nrm ${GPB_CLASSLIST_PATH}\nfi\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_filter.proto\n\n";
+ showEnvVarsInLog = 0;
+ };
+ F4B62A781AF91F6000AFCEDC /* Script: Check Runtime Stamps */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Script: Check Runtime Stamps";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "set -eu\nexec \"${SOURCE_ROOT}/DevTools/check_version_stamps.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 7461B52B0F94FAF800A0C422 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */,
+ 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */,
+ 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */,
+ F401DC2D1A8D444600FCC765 /* GPBArray.m in Sources */,
+ 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */,
+ 7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */,
+ 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */,
+ 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */,
+ 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */,
+ 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */,
+ F4353D231ABB1537005A6198 /* GPBDictionary.m in Sources */,
+ 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */,
+ 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */,
+ F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */,
+ 8B4248D21A927E1500BC1EC6 /* GPBWellKnownTypes.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8BBEA4A2147C727100C4ADB7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */,
+ F401DC331A8E5C0200FCC765 /* GPBArrayTests.m in Sources */,
+ F4353D361AC06F10005A6198 /* GPBDictionaryTests+Int64.m in Sources */,
+ F4353D391AC06F10005A6198 /* GPBDictionaryTests+UInt64.m in Sources */,
+ 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */,
+ 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */,
+ F4487C7F1AAF62CD00531423 /* GPBMessageTests+Serialization.m in Sources */,
+ 8B4248DC1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m in Sources */,
+ F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */,
+ 8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */,
+ 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
+ F4487C751AADF7F500531423 /* GPBMessageTests+Runtime.m in Sources */,
+ F4353D351AC06F10005A6198 /* GPBDictionaryTests+Int32.m in Sources */,
+ 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */,
+ 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 */,
+ 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */,
+ 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */,
+ 8B79657D14992E3F002FFBFC /* GPBRootObject.m in Sources */,
+ 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */,
+ 8B96157514CA019D00A2AC0B /* Descriptor.pbobjc.m in Sources */,
+ 8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */,
+ 8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F4487C3D1A9F8E0200531423 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F4487C521A9F8E4D00531423 /* GPBProtocolBuffers.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */;
+ targetProxy = 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */;
+ };
+ 8BD3982114BE59EB0081D629 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8BD3981414BE4AE70081D629 /* Compile_Protos */;
+ targetProxy = 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin XCBuildConfiguration section */
+ 7461B52F0F94FAFA00A0C422 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ HEADER_SEARCH_PATHS = "$(SRCROOT)";
+ PRODUCT_NAME = ProtocolBuffers;
+ };
+ name = Debug;
+ };
+ 7461B5300F94FAFA00A0C422 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ HEADER_SEARCH_PATHS = "$(SRCROOT)";
+ PRODUCT_NAME = ProtocolBuffers;
+ };
+ name = Release;
+ };
+ 8BBEA4A7147C727100C4ADB7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = YES;
+ COMBINE_HIDPI_IMAGES = YES;
+ HEADER_SEARCH_PATHS = (
+ "${PROJECT_DERIVED_FILE_DIR}/protos",
+ "$(SRCROOT)",
+ );
+ INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+ PRODUCT_NAME = UnitTests;
+ SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ };
+ name = Debug;
+ };
+ 8BBEA4A8147C727100C4ADB7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = YES;
+ COMBINE_HIDPI_IMAGES = YES;
+ HEADER_SEARCH_PATHS = (
+ "${PROJECT_DERIVED_FILE_DIR}/protos",
+ "$(SRCROOT)",
+ );
+ INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+ PRODUCT_NAME = UnitTests;
+ SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
+ };
+ name = Release;
+ };
+ 8BD3981514BE4AE70081D629 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 8BD3981614BE4AE70081D629 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
+ CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
+ CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+ GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
+ GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+ GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_PARAMETER = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ GENERATE_PROFILING_CODE = NO;
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ ONLY_ACTIVE_ARCH = YES;
+ RUN_CLANG_STATIC_ANALYZER = YES;
+ SDKROOT = macosx;
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
+ CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
+ CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
+ GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+ GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_PARAMETER = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ GENERATE_PROFILING_CODE = NO;
+ MACOSX_DEPLOYMENT_TARGET = 10.9;
+ RUN_CLANG_STATIC_ANALYZER = YES;
+ SDKROOT = macosx;
+ };
+ name = Release;
+ };
+ F4487C4F1A9F8E0200531423 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ HEADER_SEARCH_PATHS = "$(SRCROOT)";
+ PRODUCT_NAME = TestSingleSourceBuild;
+ };
+ name = Debug;
+ };
+ F4487C501A9F8E0200531423 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ COMBINE_HIDPI_IMAGES = YES;
+ HEADER_SEARCH_PATHS = "$(SRCROOT)";
+ PRODUCT_NAME = TestSingleSourceBuild;
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 7461B5330F94FAFD00A0C422 /* Build configuration list for PBXNativeTarget "ProtocolBuffers" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 7461B52F0F94FAFA00A0C422 /* Debug */,
+ 7461B5300F94FAFA00A0C422 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8BBEA4BA147C728600C4ADB7 /* Build configuration list for PBXNativeTarget "UnitTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8BBEA4A7147C727100C4ADB7 /* Debug */,
+ 8BBEA4A8147C727100C4ADB7 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8BD3981714BE4AE70081D629 /* Build configuration list for PBXAggregateTarget "Compile_Protos" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8BD3981514BE4AE70081D629 /* Debug */,
+ 8BD3981614BE4AE70081D629 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_OSX" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247B /* Debug */,
+ C01FCF5008A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F4487C4E1A9F8E0200531423 /* Build configuration list for PBXNativeTarget "TestSingleSourceBuild" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F4487C4F1A9F8E0200531423 /* Debug */,
+ F4487C501A9F8E0200531423 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..888be4da
--- /dev/null
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:ProtocolBuffers_OSX.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 00000000..08de0be8
--- /dev/null
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
+ <false/>
+</dict>
+</plist>
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
new file mode 100644
index 00000000..7083f5e3
--- /dev/null
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
@@ -0,0 +1,125 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0620"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8BBEA4A5147C727100C4ADB7"
+ BuildableName = "UnitTests.xctest"
+ BlueprintName = "UnitTests"
+ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+ </BuildableReference>
+ <SkippedTests>
+ <Test
+ Identifier = "ArrayTests">
+ </Test>
+ <Test
+ Identifier = "CodedInputStreamTests">
+ </Test>
+ <Test
+ Identifier = "CodedOutputStreamTests">
+ </Test>
+ <Test
+ Identifier = "ConcurrencyTests">
+ </Test>
+ <Test
+ Identifier = "FilteredMessageTests">
+ </Test>
+ <Test
+ Identifier = "GPBStringTests">
+ </Test>
+ <Test
+ Identifier = "GPBTestCase">
+ </Test>
+ <Test
+ Identifier = "GeneratedMessageTests">
+ </Test>
+ <Test
+ Identifier = "MessageTests">
+ </Test>
+ <Test
+ Identifier = "UnknownFieldSetTest">
+ </Test>
+ <Test
+ Identifier = "UtilitiesTests">
+ </Test>
+ <Test
+ Identifier = "WireFormatTests">
+ </Test>
+ </SkippedTests>
+ </TestableReference>
+ </Testables>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
new file mode 100644
index 00000000..f6f6e12b
--- /dev/null
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
@@ -0,0 +1,115 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0620"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "NO">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "NO"
+ buildForArchiving = "NO"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "F4487C381A9F8E0200531423"
+ BuildableName = "libTestSingleSourceBuild.a"
+ BlueprintName = "TestSingleSourceBuild"
+ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Debug">
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8BBEA4A5147C727100C4ADB7"
+ BuildableName = "UnitTests.xctest"
+ BlueprintName = "UnitTests"
+ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+ </BuildableReference>
+ <SkippedTests>
+ <Test
+ Identifier = "PerfTests">
+ </Test>
+ </SkippedTests>
+ </TestableReference>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Debug"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
new file mode 100644
index 00000000..7cf41359
--- /dev/null
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
@@ -0,0 +1,1093 @@
+// !$*UTF8*$!
+{
+ archiveVersion = 1;
+ classes = {
+ };
+ objectVersion = 47;
+ objects = {
+
+/* Begin PBXAggregateTarget section */
+ 8BD3981414BE4AE70081D629 /* Compile_Protos */ = {
+ isa = PBXAggregateTarget;
+ buildConfigurationList = 8BD3981714BE4AE70081D629 /* Build configuration list for PBXAggregateTarget "Compile_Protos" */;
+ buildPhases = (
+ 8BD3981814BE4AF30081D629 /* ShellScript */,
+ );
+ dependencies = (
+ );
+ name = Compile_Protos;
+ productName = Compile_Protos;
+ };
+/* End PBXAggregateTarget section */
+
+/* Begin PBXBuildFile section */
+ 2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */; };
+ 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */; };
+ 7461B5360F94FB4600A0C422 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */; };
+ 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */; };
+ 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */; };
+ 7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4AF0F94F99000A0C422 /* GPBField.m */; };
+ 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4BF0F94F99000A0C422 /* GPBMessage.m */; };
+ 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */; };
+ 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E60F94F99000A0C422 /* GPBUtilities.m */; };
+ 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */; };
+ 8B210CCE159383D60032D72D /* golden_message in Resources */ = {isa = PBXBuildFile; fileRef = 8B210CCD159383D60032D72D /* golden_message */; };
+ 8B210CD0159386920032D72D /* golden_packed_fields_message in Resources */ = {isa = PBXBuildFile; fileRef = 8B210CCF159386920032D72D /* golden_packed_fields_message */; };
+ 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248B31A8BD96E00BC1EC6 /* GPBSwiftTests.swift */; };
+ 8B4248E41A929C8900BC1EC6 /* GPBWellKnownTypes.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248E21A929C8900BC1EC6 /* GPBWellKnownTypes.m */; };
+ 8B4248E61A929C9900BC1EC6 /* GPBWellKnownTypesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */; };
+ 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B79657914992E3E002FFBFC /* GPBRootObject.m */; };
+ 8B79657D14992E3F002FFBFC /* GPBRootObject.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B79657914992E3E002FFBFC /* GPBRootObject.m */; };
+ 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 */; };
+ 8B9742331A89D19F00DCE92C /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8B9742321A89D19F00DCE92C /* LaunchScreen.xib */; };
+ 8B9742431A8AAA7800DCE92C /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9742421A8AAA7800DCE92C /* CoreGraphics.framework */; };
+ 8B9A5EA61831993600A9D33B /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ 8B9A5EA81831993600A9D33B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A5E9F1831913D00A9D33B /* UIKit.framework */; };
+ 8B9A5EAE1831993600A9D33B /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 8B9A5EAC1831993600A9D33B /* InfoPlist.strings */; };
+ 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 */; };
+ 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */; };
+ 8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */; };
+ 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */; };
+ 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */; };
+ 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */; };
+ 8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */; };
+ 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */; };
+ 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */; };
+ F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F41C175C1833D3310064ED4D /* GPBPerfTests.m */; };
+ F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */; };
+ F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D251ABB156F005A6198 /* GPBDictionary.m */; };
+ F4353D421AC06F31005A6198 /* GPBDictionaryTests+Bool.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3B1AC06F31005A6198 /* GPBDictionaryTests+Bool.m */; };
+ F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3C1AC06F31005A6198 /* GPBDictionaryTests+Int32.m */; };
+ F4353D441AC06F31005A6198 /* GPBDictionaryTests+Int64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3D1AC06F31005A6198 /* GPBDictionaryTests+Int64.m */; };
+ F4353D451AC06F31005A6198 /* GPBDictionaryTests+String.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */; };
+ F4353D461AC06F31005A6198 /* GPBDictionaryTests+UInt32.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */; };
+ F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */; };
+ F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */; };
+ F4487C5B1A9F8F8100531423 /* Descriptor.pbobjc.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */; };
+ F4487C6A1A9F8F8100531423 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; };
+ F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */ = {isa = PBXBuildFile; fileRef = 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */; };
+ F4487C731A9F906200531423 /* GPBArray.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C711A9F906200531423 /* GPBArray.m */; };
+ F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */; };
+ F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */; };
+ F4487C851AAF6AC500531423 /* GPBMessageTests+Merge.m in Sources */ = {isa = PBXBuildFile; fileRef = F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */; };
+ F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */ = {isa = PBXBuildFile; fileRef = F45C69CB16DFD08D0081955B /* GPBExtensionField.m */; };
+ F45E57C91AE6DC98000B7D99 /* text_format_map_unittest_data.txt in Resources */ = {isa = PBXBuildFile; fileRef = F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */; };
+/* End PBXBuildFile section */
+
+/* Begin PBXContainerItemProxy section */
+ 8B9A5ED01831994600A9D33B /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8B9A5EA41831993600A9D33B;
+ remoteInfo = iOSTestHarness;
+ };
+ 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 7461B52D0F94FAF800A0C422;
+ remoteInfo = ProtocolBuffers;
+ };
+ 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */ = {
+ isa = PBXContainerItemProxy;
+ containerPortal = 29B97313FDCFA39411CA2CEA /* Project object */;
+ proxyType = 1;
+ remoteGlobalIDString = 8BD3981414BE4AE70081D629;
+ remoteInfo = Compile_Protos;
+ };
+/* End PBXContainerItemProxy section */
+
+/* Begin PBXFileReference section */
+ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
+ 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBConcurrencyTests.m; sourceTree = "<group>"; };
+ 51457B5F18D0B7AF00CCC606 /* GPBCodedInputStream_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBCodedInputStream_PackagePrivate.h; sourceTree = "<group>"; };
+ 515B840C18B7DEE30031753B /* GPBDescriptor_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDescriptor_PackagePrivate.h; sourceTree = "<group>"; };
+ 5196A06918CE16B000B759E2 /* GPBMessage_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBMessage_PackagePrivate.h; sourceTree = "<group>"; };
+ 7401C1A90F950347006D8281 /* UnitTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "UnitTests-Info.plist"; sourceTree = "<group>"; };
+ 7461B48D0F94F99000A0C422 /* GPBBootstrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBBootstrap.h; sourceTree = "<group>"; };
+ 7461B48E0F94F99000A0C422 /* GPBCodedInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBCodedInputStream.h; sourceTree = "<group>"; };
+ 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = GPBCodedInputStream.m; sourceTree = "<group>"; };
+ 7461B4900F94F99000A0C422 /* GPBCodedOutputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBCodedOutputStream.h; sourceTree = "<group>"; };
+ 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOutputStream.m; sourceTree = "<group>"; };
+ 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionRegistry.h; sourceTree = "<group>"; };
+ 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionRegistry.m; sourceTree = "<group>"; };
+ 7461B4AE0F94F99000A0C422 /* GPBField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBField.h; sourceTree = "<group>"; };
+ 7461B4AF0F94F99000A0C422 /* GPBField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBField.m; sourceTree = "<group>"; };
+ 7461B4BE0F94F99000A0C422 /* GPBMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBMessage.h; sourceTree = "<group>"; };
+ 7461B4BF0F94F99000A0C422 /* GPBMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessage.m; sourceTree = "<group>"; };
+ 7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers.h; sourceTree = "<group>"; };
+ 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet.h; sourceTree = "<group>"; };
+ 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSet.m; sourceTree = "<group>"; };
+ 7461B4E50F94F99000A0C422 /* GPBUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBUtilities.h; sourceTree = "<group>"; };
+ 7461B4E60F94F99000A0C422 /* GPBUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilities.m; sourceTree = "<group>"; };
+ 7461B4E70F94F99000A0C422 /* GPBWireFormat.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWireFormat.h; sourceTree = "<group>"; };
+ 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormat.m; sourceTree = "<group>"; };
+ 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libProtocolBuffers.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedInputStreamTests.m; sourceTree = "<group>"; };
+ 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOuputStreamTests.m; sourceTree = "<group>"; };
+ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessageTests.m; sourceTree = "<group>"; };
+ 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTestUtilities.h; sourceTree = "<group>"; };
+ 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTestUtilities.m; sourceTree = "<group>"; };
+ 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnknownFieldSetTest.m; sourceTree = "<group>"; };
+ 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUtilitiesTests.m; sourceTree = "<group>"; };
+ 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormatTests.m; sourceTree = "<group>"; };
+ 748F0CAF0FD70602000858A9 /* GPBExtensionField.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField.h; sourceTree = "<group>"; };
+ 8B09AAF614B663A7007B4184 /* unittest_objc.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_objc.proto; sourceTree = "<group>"; };
+ 8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Filter1.txt; sourceTree = "<group>"; };
+ 8B20A9A916F1BC0600BE3EAD /* unittest_filter.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_filter.proto; sourceTree = "<group>"; };
+ 8B210CCD159383D60032D72D /* golden_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_message; sourceTree = "<group>"; };
+ 8B210CCF159386920032D72D /* golden_packed_fields_message */ = {isa = PBXFileReference; lastKnownFileType = file; path = golden_packed_fields_message; sourceTree = "<group>"; };
+ 8B4248B21A8BD96D00BC1EC6 /* UnitTests-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "UnitTests-Bridging-Header.h"; sourceTree = "<group>"; };
+ 8B4248B31A8BD96E00BC1EC6 /* GPBSwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GPBSwiftTests.swift; sourceTree = "<group>"; };
+ 8B4248B71A8BDD9600BC1EC6 /* protobuf */ = {isa = PBXFileReference; lastKnownFileType = text; name = protobuf; path = ../../Intermediates/ProtocolBuffers_iOS.build/DerivedSources/protos/google/protobuf; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8B4248DD1A929C7D00BC1EC6 /* Duration.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Duration.pbobjc.h; path = google/protobuf/Duration.pbobjc.h; sourceTree = "<group>"; };
+ 8B4248DE1A929C7D00BC1EC6 /* Duration.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Duration.pbobjc.m; path = google/protobuf/Duration.pbobjc.m; sourceTree = "<group>"; };
+ 8B4248DF1A929C7D00BC1EC6 /* Timestamp.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Timestamp.pbobjc.h; path = /google/protobuf/Timestamp.pbobjc.h; sourceTree = "<group>"; };
+ 8B4248E01A929C7D00BC1EC6 /* Timestamp.pbobjc.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; name = Timestamp.pbobjc.m; path = google/protobuf/Timestamp.pbobjc.m; sourceTree = "<group>"; };
+ 8B4248E11A929C8900BC1EC6 /* GPBWellKnownTypes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBWellKnownTypes.h; sourceTree = "<group>"; };
+ 8B4248E21A929C8900BC1EC6 /* GPBWellKnownTypes.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypes.m; sourceTree = "<group>"; };
+ 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWellKnownTypesTest.m; sourceTree = "<group>"; };
+ 8B4249481A92A02300BC1EC6 /* timestamp.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = timestamp.proto; path = ../src/google/protobuf/timestamp.proto; sourceTree = "<group>"; };
+ 8B4249491A92A0BA00BC1EC6 /* descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = descriptor.proto; path = ../src/google/protobuf/descriptor.proto; sourceTree = "<group>"; };
+ 8B42494A1A92A0BA00BC1EC6 /* duration.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = duration.proto; path = ../src/google/protobuf/duration.proto; sourceTree = "<group>"; };
+ 8B54585814DCC34E003D7338 /* Descriptor.pbobjc.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = Descriptor.pbobjc.h; path = /google/protobuf/Descriptor.pbobjc.h; sourceTree = SOURCE_ROOT; };
+ 8B79657814992E3E002FFBFC /* GPBRootObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBRootObject.h; sourceTree = "<group>"; };
+ 8B79657914992E3E002FFBFC /* GPBRootObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBRootObject.m; sourceTree = "<group>"; };
+ 8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_custom_options.proto; path = ../../src/google/protobuf/unittest_custom_options.proto; sourceTree = "<group>"; };
+ 8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_embed_optimize_for.proto; path = ../../src/google/protobuf/unittest_embed_optimize_for.proto; sourceTree = "<group>"; };
+ 8B7E6A7614893DBA00F8884A /* unittest_empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_empty.proto; path = ../../src/google/protobuf/unittest_empty.proto; sourceTree = "<group>"; };
+ 8B7E6A7814893DBB00F8884A /* unittest_import.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_import.proto; path = ../../src/google/protobuf/unittest_import.proto; sourceTree = "<group>"; };
+ 8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_mset.proto; path = ../../src/google/protobuf/unittest_mset.proto; sourceTree = "<group>"; };
+ 8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_no_generic_services.proto; path = ../../src/google/protobuf/unittest_no_generic_services.proto; sourceTree = "<group>"; };
+ 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_optimize_for.proto; path = ../../src/google/protobuf/unittest_optimize_for.proto; sourceTree = "<group>"; };
+ 8B7E6A7E14893DBC00F8884A /* unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest.proto; path = ../../src/google/protobuf/unittest.proto; sourceTree = "<group>"; };
+ 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>"; };
+ 8B9742321A89D19F00DCE92C /* LaunchScreen.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LaunchScreen.xib; sourceTree = "<group>"; };
+ 8B9742421A8AAA7800DCE92C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
+ 8B9A5E9F1831913D00A9D33B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
+ 8B9A5EA51831993600A9D33B /* iOSTestHarness.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = iOSTestHarness.app; sourceTree = BUILT_PRODUCTS_DIR; };
+ 8B9A5EAB1831993600A9D33B /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
+ 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; };
+ 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBFilteredMessageTests.m; sourceTree = "<group>"; };
+ 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = "<group>"; };
+ 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = "<group>"; };
+ 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = "<group>"; };
+ 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = Descriptor.pbobjc.m; path = google/protobuf/Descriptor.pbobjc.m; sourceTree = SOURCE_ROOT; };
+ 8BEB5AE01498033E0078BF9D /* GPBTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBTypes.h; sourceTree = "<group>"; };
+ F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArrayTests.m; sourceTree = "<group>"; };
+ F41C175C1833D3310064ED4D /* GPBPerfTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBPerfTests.m; sourceTree = "<group>"; };
+ F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptorTests.m; sourceTree = "<group>"; };
+ F4353D241ABB156F005A6198 /* GPBDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDictionary.h; sourceTree = "<group>"; };
+ F4353D251ABB156F005A6198 /* GPBDictionary.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDictionary.m; sourceTree = "<group>"; };
+ F4353D3A1AC06F31005A6198 /* GPBDictionaryTests.pddm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = GPBDictionaryTests.pddm; sourceTree = "<group>"; };
+ F4353D3B1AC06F31005A6198 /* GPBDictionaryTests+Bool.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+Bool.m"; sourceTree = "<group>"; };
+ F4353D3C1AC06F31005A6198 /* GPBDictionaryTests+Int32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+Int32.m"; sourceTree = "<group>"; };
+ F4353D3D1AC06F31005A6198 /* GPBDictionaryTests+Int64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+Int64.m"; sourceTree = "<group>"; };
+ F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+String.m"; sourceTree = "<group>"; };
+ F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt32.m"; sourceTree = "<group>"; };
+ F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBDictionaryTests+UInt64.m"; sourceTree = "<group>"; };
+ F43725921AC9835D004DCAFB /* GPBDictionary_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDictionary_PackagePrivate.h; sourceTree = "<group>"; };
+ F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_unittest_data.txt; sourceTree = "<group>"; };
+ F4411BE81AF1301700324B4A /* GPBArray_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBArray_PackagePrivate.h; sourceTree = "<group>"; };
+ F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libTestSingleSourceBuild.a; sourceTree = BUILT_PRODUCTS_DIR; };
+ F4487C701A9F906200531423 /* GPBArray.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBArray.h; sourceTree = "<group>"; };
+ F4487C711A9F906200531423 /* GPBArray.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBArray.m; sourceTree = "<group>"; };
+ F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Runtime.m"; sourceTree = "<group>"; };
+ F4487C7A1AADFB5500531423 /* unittest_runtime_proto2.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_runtime_proto2.proto; sourceTree = "<group>"; };
+ F4487C7B1AADFB5500531423 /* unittest_runtime_proto3.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_runtime_proto3.proto; sourceTree = "<group>"; };
+ F4487C7D1AAE06C500531423 /* GPBUtilities_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUtilities_PackagePrivate.h; sourceTree = "<group>"; };
+ F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Serialization.m"; sourceTree = "<group>"; };
+ F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Merge.m"; sourceTree = "<group>"; };
+ F44B25D81A729803005CCF68 /* Filter2.txt */ = {isa = PBXFileReference; lastKnownFileType = text; path = Filter2.txt; sourceTree = "<group>"; };
+ F451D3F61A8AAEA600B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers_RuntimeSupport.h; sourceTree = "<group>"; };
+ F45C69CB16DFD08D0081955B /* GPBExtensionField.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionField.m; sourceTree = "<group>"; };
+ F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = text_format_map_unittest_data.txt; sourceTree = "<group>"; };
+ F4AC9E1C1A8BEB1000BD6E83 /* unittest_cycle.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_cycle.proto; sourceTree = "<group>"; };
+ F4B6B8B01A9CC99500892426 /* GPBField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBField_PackagePrivate.h; sourceTree = "<group>"; };
+ F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBUnknownFieldSet_PackagePrivate.h; sourceTree = "<group>"; };
+ F4B6B8B31A9CD1C600892426 /* GPBExtensionField_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionField_PackagePrivate.h; sourceTree = "<group>"; };
+ F4B6B8B41A9CD1C600892426 /* GPBExtensionRegistry_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBExtensionRegistry_PackagePrivate.h; sourceTree = "<group>"; };
+ F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRootObject_PackagePrivate.h; sourceTree = "<group>"; };
+ F4B6B8BA1A9D343B00892426 /* unittest_name_mangling.proto */ = {isa = PBXFileReference; lastKnownFileType = text; path = unittest_name_mangling.proto; sourceTree = "<group>"; };
+/* End PBXFileReference section */
+
+/* Begin PBXFrameworksBuildPhase section */
+ 7461B52C0F94FAF800A0C422 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 7461B5360F94FB4600A0C422 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8B9A5EA21831993600A9D33B /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8B9742431A8AAA7800DCE92C /* CoreGraphics.framework in Frameworks */,
+ 8B9A5EA81831993600A9D33B /* UIKit.framework in Frameworks */,
+ 8B9A5EA61831993600A9D33B /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8BBEA4A3147C727100C4ADB7 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8BBEA4BB147C729200C4ADB7 /* libProtocolBuffers.a in Frameworks */,
+ 8B9A5EEC18330A0F00A9D33B /* UIKit.framework in Frameworks */,
+ 8BF8193514A0DDA600A2C982 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F4487C691A9F8F8100531423 /* Frameworks */ = {
+ isa = PBXFrameworksBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F4487C6A1A9F8F8100531423 /* Foundation.framework in Frameworks */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXFrameworksBuildPhase section */
+
+/* Begin PBXGroup section */
+ 080E96DDFE201D6D7F000001 /* Core Source */ = {
+ isa = PBXGroup;
+ children = (
+ 7461B4CD0F94F99000A0C422 /* GPBProtocolBuffers.h */,
+ F451D3F61A8AAEA600B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */,
+ 8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */,
+ 7461B3C50F94F84100A0C422 /* Extensions */,
+ 7461B4850F94F96600A0C422 /* Fields */,
+ 7461B4860F94F96B00A0C422 /* IO */,
+ 7461B5150F94FA7300A0C422 /* Messages */,
+ 8BCF334414ED727300BC5317 /* Support */,
+ 29B97315FDCFA39411CA2CEA /* Generated */,
+ );
+ name = "Core Source";
+ sourceTree = "<group>";
+ };
+ 19C28FACFE9D520D11CA2CBB /* Products */ = {
+ isa = PBXGroup;
+ children = (
+ 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */,
+ 8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */,
+ 8B9A5EA51831993600A9D33B /* iOSTestHarness.app */,
+ F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */,
+ );
+ name = Products;
+ sourceTree = "<group>";
+ };
+ 29B97314FDCFA39411CA2CEA /* CustomTemplate */ = {
+ isa = PBXGroup;
+ children = (
+ 080E96DDFE201D6D7F000001 /* Core Source */,
+ 7461B6940F94FDDD00A0C422 /* Tests */,
+ 29B97323FDCFA39411CA2CEA /* Frameworks */,
+ 19C28FACFE9D520D11CA2CBB /* Products */,
+ );
+ name = CustomTemplate;
+ sourceTree = "<group>";
+ };
+ 29B97315FDCFA39411CA2CEA /* Generated */ = {
+ isa = PBXGroup;
+ children = (
+ 8B4249491A92A0BA00BC1EC6 /* descriptor.proto */,
+ 8BD3982214BE5B0C0081D629 /* Descriptor.pbobjc.m */,
+ 8B54585814DCC34E003D7338 /* Descriptor.pbobjc.h */,
+ 8B42494A1A92A0BA00BC1EC6 /* duration.proto */,
+ 8B4248DD1A929C7D00BC1EC6 /* Duration.pbobjc.h */,
+ 8B4248DE1A929C7D00BC1EC6 /* Duration.pbobjc.m */,
+ 8B4249481A92A02300BC1EC6 /* timestamp.proto */,
+ 8B4248DF1A929C7D00BC1EC6 /* Timestamp.pbobjc.h */,
+ 8B4248E01A929C7D00BC1EC6 /* Timestamp.pbobjc.m */,
+ );
+ name = Generated;
+ sourceTree = "<group>";
+ };
+ 29B97323FDCFA39411CA2CEA /* Frameworks */ = {
+ isa = PBXGroup;
+ children = (
+ 8B9742421A8AAA7800DCE92C /* CoreGraphics.framework */,
+ 8B9A5E9F1831913D00A9D33B /* UIKit.framework */,
+ 1D30AB110D05D00D00671497 /* Foundation.framework */,
+ );
+ name = Frameworks;
+ sourceTree = "<group>";
+ };
+ 7461B3C50F94F84100A0C422 /* Extensions */ = {
+ isa = PBXGroup;
+ children = (
+ F4B6B8B31A9CD1C600892426 /* GPBExtensionField_PackagePrivate.h */,
+ 748F0CAF0FD70602000858A9 /* GPBExtensionField.h */,
+ F45C69CB16DFD08D0081955B /* GPBExtensionField.m */,
+ F4B6B8B41A9CD1C600892426 /* GPBExtensionRegistry_PackagePrivate.h */,
+ 7461B4A80F94F99000A0C422 /* GPBExtensionRegistry.h */,
+ 7461B4A90F94F99000A0C422 /* GPBExtensionRegistry.m */,
+ F4B6B8B51A9CD1C600892426 /* GPBRootObject_PackagePrivate.h */,
+ 8B79657814992E3E002FFBFC /* GPBRootObject.h */,
+ 8B79657914992E3E002FFBFC /* GPBRootObject.m */,
+ );
+ name = Extensions;
+ sourceTree = "<group>";
+ };
+ 7461B4850F94F96600A0C422 /* Fields */ = {
+ isa = PBXGroup;
+ children = (
+ F4B6B8B01A9CC99500892426 /* GPBField_PackagePrivate.h */,
+ 7461B4AE0F94F99000A0C422 /* GPBField.h */,
+ 7461B4AF0F94F99000A0C422 /* GPBField.m */,
+ F4B6B8B11A9CCBBB00892426 /* GPBUnknownFieldSet_PackagePrivate.h */,
+ 7461B4E10F94F99000A0C422 /* GPBUnknownFieldSet.h */,
+ 7461B4E20F94F99000A0C422 /* GPBUnknownFieldSet.m */,
+ );
+ name = Fields;
+ sourceTree = "<group>";
+ };
+ 7461B4860F94F96B00A0C422 /* IO */ = {
+ isa = PBXGroup;
+ children = (
+ 7461B48E0F94F99000A0C422 /* GPBCodedInputStream.h */,
+ 51457B5F18D0B7AF00CCC606 /* GPBCodedInputStream_PackagePrivate.h */,
+ 7461B48F0F94F99000A0C422 /* GPBCodedInputStream.m */,
+ 7461B4900F94F99000A0C422 /* GPBCodedOutputStream.h */,
+ 7461B4910F94F99000A0C422 /* GPBCodedOutputStream.m */,
+ 7461B4E70F94F99000A0C422 /* GPBWireFormat.h */,
+ 7461B4E80F94F99000A0C422 /* GPBWireFormat.m */,
+ );
+ name = IO;
+ sourceTree = "<group>";
+ };
+ 7461B5150F94FA7300A0C422 /* Messages */ = {
+ isa = PBXGroup;
+ children = (
+ 515B840C18B7DEE30031753B /* GPBDescriptor_PackagePrivate.h */,
+ 8B96157214C8B06000A2AC0B /* GPBDescriptor.h */,
+ 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */,
+ 7461B4BE0F94F99000A0C422 /* GPBMessage.h */,
+ 5196A06918CE16B000B759E2 /* GPBMessage_PackagePrivate.h */,
+ 7461B4BF0F94F99000A0C422 /* GPBMessage.m */,
+ );
+ name = Messages;
+ sourceTree = "<group>";
+ };
+ 7461B6940F94FDDD00A0C422 /* Tests */ = {
+ isa = PBXGroup;
+ children = (
+ 8B9A5EA91831993600A9D33B /* iOSTestHarness */,
+ 8B4248B71A8BDD9600BC1EC6 /* protobuf */,
+ 8B20A9A816F1BBFA00BE3EAD /* Filter1.txt */,
+ F44B25D81A729803005CCF68 /* Filter2.txt */,
+ 8B210CCD159383D60032D72D /* golden_message */,
+ 8B210CCF159386920032D72D /* golden_packed_fields_message */,
+ 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */,
+ F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */,
+ 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */,
+ 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */,
+ 5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */,
+ F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */,
+ F4353D3A1AC06F31005A6198 /* GPBDictionaryTests.pddm */,
+ F4353D3B1AC06F31005A6198 /* GPBDictionaryTests+Bool.m */,
+ F4353D3C1AC06F31005A6198 /* GPBDictionaryTests+Int32.m */,
+ F4353D3D1AC06F31005A6198 /* GPBDictionaryTests+Int64.m */,
+ F4353D3E1AC06F31005A6198 /* GPBDictionaryTests+String.m */,
+ F4353D3F1AC06F31005A6198 /* GPBDictionaryTests+UInt32.m */,
+ F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */,
+ 8BCC29BE16FD09A000F29F4A /* GPBFilteredMessageTests.m */,
+ 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */,
+ F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */,
+ F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */,
+ F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */,
+ F41C175C1833D3310064ED4D /* GPBPerfTests.m */,
+ 8BA9364418DA5F4B0056FA2A /* GPBStringTests.m */,
+ 8B4248B31A8BD96E00BC1EC6 /* GPBSwiftTests.swift */,
+ 7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */,
+ 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */,
+ 8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */,
+ 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */,
+ 7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */,
+ 8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */,
+ 7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */,
+ F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */,
+ F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */,
+ 8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */,
+ F4AC9E1C1A8BEB1000BD6E83 /* unittest_cycle.proto */,
+ 8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */,
+ 8B7E6A7614893DBA00F8884A /* unittest_empty.proto */,
+ 8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */,
+ 8B20A9A916F1BC0600BE3EAD /* unittest_filter.proto */,
+ 8B7E6A7814893DBB00F8884A /* unittest_import.proto */,
+ 8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */,
+ 8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */,
+ F4B6B8BA1A9D343B00892426 /* unittest_name_mangling.proto */,
+ 8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */,
+ 8B09AAF614B663A7007B4184 /* unittest_objc.proto */,
+ 8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */,
+ F4487C7A1AADFB5500531423 /* unittest_runtime_proto2.proto */,
+ F4487C7B1AADFB5500531423 /* unittest_runtime_proto3.proto */,
+ 8B7E6A7E14893DBC00F8884A /* unittest.proto */,
+ 8B4248B21A8BD96D00BC1EC6 /* UnitTests-Bridging-Header.h */,
+ 7401C1A90F950347006D8281 /* UnitTests-Info.plist */,
+ );
+ path = Tests;
+ sourceTree = "<group>";
+ };
+ 8B9A5EA91831993600A9D33B /* iOSTestHarness */ = {
+ isa = PBXGroup;
+ children = (
+ 8B9A5EB31831993600A9D33B /* AppDelegate.m */,
+ 8B9A5EB51831993600A9D33B /* Images.xcassets */,
+ 8B9A5EAA1831993600A9D33B /* Supporting Files */,
+ 8B9742321A89D19F00DCE92C /* LaunchScreen.xib */,
+ );
+ path = iOSTestHarness;
+ sourceTree = "<group>";
+ };
+ 8B9A5EAA1831993600A9D33B /* Supporting Files */ = {
+ isa = PBXGroup;
+ children = (
+ 8B9A5EAB1831993600A9D33B /* Info.plist */,
+ 8B9A5EAC1831993600A9D33B /* InfoPlist.strings */,
+ );
+ name = "Supporting Files";
+ sourceTree = "<group>";
+ };
+ 8BCF334414ED727300BC5317 /* Support */ = {
+ isa = PBXGroup;
+ children = (
+ F4411BE81AF1301700324B4A /* GPBArray_PackagePrivate.h */,
+ F4487C701A9F906200531423 /* GPBArray.h */,
+ F4487C711A9F906200531423 /* GPBArray.m */,
+ 7461B48D0F94F99000A0C422 /* GPBBootstrap.h */,
+ F43725921AC9835D004DCAFB /* GPBDictionary_PackagePrivate.h */,
+ F4353D241ABB156F005A6198 /* GPBDictionary.h */,
+ F4353D251ABB156F005A6198 /* GPBDictionary.m */,
+ 8BEB5AE01498033E0078BF9D /* GPBTypes.h */,
+ F4487C7D1AAE06C500531423 /* GPBUtilities_PackagePrivate.h */,
+ 7461B4E50F94F99000A0C422 /* GPBUtilities.h */,
+ 7461B4E60F94F99000A0C422 /* GPBUtilities.m */,
+ 8B4248E11A929C8900BC1EC6 /* GPBWellKnownTypes.h */,
+ 8B4248E21A929C8900BC1EC6 /* GPBWellKnownTypes.m */,
+ );
+ name = Support;
+ sourceTree = "<group>";
+ };
+/* End PBXGroup section */
+
+/* Begin PBXHeadersBuildPhase section */
+ 7461B52A0F94FAF800A0C422 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F4487C561A9F8F8100531423 /* Headers */ = {
+ isa = PBXHeadersBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXHeadersBuildPhase section */
+
+/* Begin PBXNativeTarget section */
+ 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 7461B5330F94FAFD00A0C422 /* Build configuration list for PBXNativeTarget "ProtocolBuffers" */;
+ buildPhases = (
+ 7461B52A0F94FAF800A0C422 /* Headers */,
+ 7461B52B0F94FAF800A0C422 /* Sources */,
+ 7461B52C0F94FAF800A0C422 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = ProtocolBuffers;
+ productName = "ProtocolBuffers-iPhoneDevice";
+ productReference = 7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+ 8B9A5EA41831993600A9D33B /* iOSTestHarness */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8B9A5ECA1831993600A9D33B /* Build configuration list for PBXNativeTarget "iOSTestHarness" */;
+ buildPhases = (
+ 8B9A5EA11831993600A9D33B /* Sources */,
+ 8B9A5EA21831993600A9D33B /* Frameworks */,
+ 8B9A5EA31831993600A9D33B /* Resources */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = iOSTestHarness;
+ productName = iOSTestHarness;
+ productReference = 8B9A5EA51831993600A9D33B /* iOSTestHarness.app */;
+ productType = "com.apple.product-type.application";
+ };
+ 8BBEA4A5147C727100C4ADB7 /* UnitTests */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = 8BBEA4BA147C728600C4ADB7 /* Build configuration list for PBXNativeTarget "UnitTests" */;
+ buildPhases = (
+ F4B62A791AF91F7500AFCEDC /* Script: Check Runtime Stamps */,
+ 8BBEA4A1147C727100C4ADB7 /* Resources */,
+ 8BBEA4A2147C727100C4ADB7 /* Sources */,
+ 8BBEA4A3147C727100C4ADB7 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */,
+ 8BD3982114BE59EB0081D629 /* PBXTargetDependency */,
+ 8B9A5ED11831994600A9D33B /* PBXTargetDependency */,
+ );
+ name = UnitTests;
+ productName = UnitTests;
+ productReference = 8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */;
+ productType = "com.apple.product-type.bundle.unit-test";
+ };
+ F4487C551A9F8F8100531423 /* TestSingleSourceBuild */ = {
+ isa = PBXNativeTarget;
+ buildConfigurationList = F4487C6B1A9F8F8100531423 /* Build configuration list for PBXNativeTarget "TestSingleSourceBuild" */;
+ buildPhases = (
+ F4487C561A9F8F8100531423 /* Headers */,
+ F4487C5A1A9F8F8100531423 /* Sources */,
+ F4487C691A9F8F8100531423 /* Frameworks */,
+ );
+ buildRules = (
+ );
+ dependencies = (
+ );
+ name = TestSingleSourceBuild;
+ productName = "ProtocolBuffers-iPhoneDevice";
+ productReference = F4487C6E1A9F8F8100531423 /* libTestSingleSourceBuild.a */;
+ productType = "com.apple.product-type.library.static";
+ };
+/* End PBXNativeTarget section */
+
+/* Begin PBXProject section */
+ 29B97313FDCFA39411CA2CEA /* Project object */ = {
+ isa = PBXProject;
+ attributes = {
+ LastTestingUpgradeCheck = 0600;
+ LastUpgradeCheck = 0610;
+ TargetAttributes = {
+ 8BBEA4A5147C727100C4ADB7 = {
+ TestTargetID = 8B9A5EA41831993600A9D33B;
+ };
+ };
+ };
+ buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_iOS" */;
+ compatibilityVersion = "Xcode 6.3";
+ developmentRegion = English;
+ hasScannedForEncodings = 1;
+ knownRegions = (
+ en,
+ );
+ mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
+ projectDirPath = "";
+ projectRoot = "";
+ targets = (
+ 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */,
+ 8BBEA4A5147C727100C4ADB7 /* UnitTests */,
+ 8BD3981414BE4AE70081D629 /* Compile_Protos */,
+ 8B9A5EA41831993600A9D33B /* iOSTestHarness */,
+ F4487C551A9F8F8100531423 /* TestSingleSourceBuild */,
+ );
+ };
+/* End PBXProject section */
+
+/* Begin PBXResourcesBuildPhase section */
+ 8B9A5EA31831993600A9D33B /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8B9A5EAE1831993600A9D33B /* InfoPlist.strings in Resources */,
+ 8B9A5EB61831993600A9D33B /* Images.xcassets in Resources */,
+ 8B9742331A89D19F00DCE92C /* LaunchScreen.xib in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8BBEA4A1147C727100C4ADB7 /* Resources */ = {
+ isa = PBXResourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8B210CCE159383D60032D72D /* golden_message in Resources */,
+ F43C88D0191D77FC009E917D /* text_format_unittest_data.txt in Resources */,
+ 8B210CD0159386920032D72D /* golden_packed_fields_message in Resources */,
+ F45E57C91AE6DC98000B7D99 /* text_format_map_unittest_data.txt in Resources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXResourcesBuildPhase section */
+
+/* Begin PBXShellScriptBuildPhase section */
+ 8BD3981814BE4AF30081D629 /* ShellScript */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ "$(SRCROOT)/../src/google/protobuf/unittest_custom_options.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_embed_optimize_for.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_empty.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_enormous_descriptor.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_import_lite.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_import.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_lite_imports_nonlite.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_lite.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_mset.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_no_generic_services.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest.proto",
+ "$(SRCROOT)/Tests/unittest_objc.proto",
+ "$(SRCROOT)/../src/.libs/libprotoc.10.dylib",
+ "$(SRCROOT)/../src/google/protobuf/unittest_import_public_lite.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_import_public.proto",
+ "$(SRCROOT)/Tests/unittest_filter.proto",
+ "$(SRCROOT)/../src/.libs/libprotobuf.10.dylib",
+ "$(SRCROOT)/../src/.libs/protoc",
+ "$(SRCROOT)/Tests/Filter1.txt",
+ "$(SRCROOT)/Tests/Filter2.txt",
+ "$(SRCROOT)/Tests/unittest_cycle.proto",
+ "$(SRCROOT)/Tests/unittest_name_mangling.proto",
+ "$(SRCROOT)/Tests/unittest_runtime_proto2.proto",
+ "$(SRCROOT)/Tests/unittest_runtime_proto3.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_drop_unknown_fields.proto",
+ "$(SRCROOT)/../src/google/protobuf/unittest_preserve_unknown_enum.proto",
+ "$(SRCROOT)/../src/google/protobuf/map_lite_unittest.proto",
+ "$(SRCROOT)/../src/google/protobuf/map_proto2_unittest.proto",
+ "$(SRCROOT)/../src/google/protobuf/map_unittest.proto",
+ );
+ outputPaths = (
+ "$(PROJECT_DERIVED_FILE_DIR)/protos/google/protobuf/Unittest.pbobjc.h",
+ "$(PROJECT_DERIVED_FILE_DIR)/protos/google/protobuf/Unittest.pbobjc.m",
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/bash;
+ shellScript = "set -eu\nmkdir -p \"${PROJECT_DERIVED_FILE_DIR}/protos\"\nexport PATH=\"${PATH}:.\"\ncd \"${SRCROOT}\"/../src\n\nPROTOC=./protoc\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_custom_options.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_enormous_descriptor.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_embed_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_empty.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_mset.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_no_generic_services.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_optimize_for.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_import_public_lite.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_drop_unknown_fields.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/unittest_preserve_unknown_enum.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_lite_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_proto2_unittest.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. google/protobuf/map_unittest.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=google/protobuf/ --proto_path=. --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_objc.proto\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_cycle.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_name_mangling.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto2.proto\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_runtime_proto3.proto\n\nexport GPB_CLASSLIST_PATH=\"${PROJECT_DERIVED_FILE_DIR}/ClassList.txt\"\nexport GPB_OBJC_CLASS_WHITELIST_PATHS=\"${SRCROOT}/Tests/Filter1.txt;${SRCROOT}/Tests/Filter2.txt\"\n\nif [ -e ${GPB_CLASSLIST_PATH} ]; then\nrm ${GPB_CLASSLIST_PATH}\nfi\n\n$PROTOC --objc_out=\"${PROJECT_DERIVED_FILE_DIR}/protos/google/protobuf\" --proto_path=\"${SRCROOT}\"/Tests \"${SRCROOT}\"/Tests/unittest_filter.proto\n\n";
+ showEnvVarsInLog = 0;
+ };
+ F4B62A791AF91F7500AFCEDC /* Script: Check Runtime Stamps */ = {
+ isa = PBXShellScriptBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ );
+ inputPaths = (
+ );
+ name = "Script: Check Runtime Stamps";
+ outputPaths = (
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ shellPath = /bin/sh;
+ shellScript = "set -eu\nexec \"${SOURCE_ROOT}/DevTools/check_version_stamps.sh\"\n";
+ showEnvVarsInLog = 0;
+ };
+/* End PBXShellScriptBuildPhase section */
+
+/* Begin PBXSourcesBuildPhase section */
+ 7461B52B0F94FAF800A0C422 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 2CFB390415C718CE00CBF84D /* Descriptor.pbobjc.m in Sources */,
+ 7461B53C0F94FB4E00A0C422 /* GPBCodedInputStream.m in Sources */,
+ F4487C731A9F906200531423 /* GPBArray.m in Sources */,
+ 7461B53D0F94FB4E00A0C422 /* GPBCodedOutputStream.m in Sources */,
+ 7461B5490F94FB4E00A0C422 /* GPBExtensionRegistry.m in Sources */,
+ 7461B54C0F94FB4E00A0C422 /* GPBField.m in Sources */,
+ 7461B5530F94FB4E00A0C422 /* GPBMessage.m in Sources */,
+ 7461B5610F94FB4E00A0C422 /* GPBUnknownFieldSet.m in Sources */,
+ 7461B5630F94FB4E00A0C422 /* GPBUtilities.m in Sources */,
+ 7461B5640F94FB4E00A0C422 /* GPBWireFormat.m in Sources */,
+ F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */,
+ 8B79657B14992E3F002FFBFC /* GPBRootObject.m in Sources */,
+ 8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */,
+ F45C69CC16DFD08D0081955B /* GPBExtensionField.m in Sources */,
+ 8B4248E41A929C8900BC1EC6 /* GPBWellKnownTypes.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8B9A5EA11831993600A9D33B /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8B9A5EB41831993600A9D33B /* AppDelegate.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ 8BBEA4A2147C727100C4ADB7 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ 8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */,
+ F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */,
+ F4353D441AC06F31005A6198 /* GPBDictionaryTests+Int64.m in Sources */,
+ F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */,
+ 8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */,
+ 8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */,
+ F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */,
+ 8B4248E61A929C9900BC1EC6 /* GPBWellKnownTypesTest.m in Sources */,
+ F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */,
+ 8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */,
+ 5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
+ F4487C771AADF84900531423 /* GPBMessageTests+Runtime.m in Sources */,
+ F4353D431AC06F31005A6198 /* GPBDictionaryTests+Int32.m in Sources */,
+ 8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */,
+ 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 */,
+ 8BBEA4B7147C727D00C4ADB7 /* GPBUtilitiesTests.m in Sources */,
+ 8BBEA4B8147C727D00C4ADB7 /* GPBWireFormatTests.m in Sources */,
+ 8B79657D14992E3F002FFBFC /* GPBRootObject.m in Sources */,
+ 8BD3981F14BE59D70081D629 /* GPBUnittestProtos.m in Sources */,
+ 8B96157514CA019D00A2AC0B /* Descriptor.pbobjc.m in Sources */,
+ 8BCC29BF16FD09A000F29F4A /* GPBFilteredMessageTests.m in Sources */,
+ 8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+ F4487C5A1A9F8F8100531423 /* Sources */ = {
+ isa = PBXSourcesBuildPhase;
+ buildActionMask = 2147483647;
+ files = (
+ F4487C5B1A9F8F8100531423 /* Descriptor.pbobjc.m in Sources */,
+ F4487C6F1A9F8FFF00531423 /* GPBProtocolBuffers.m in Sources */,
+ );
+ runOnlyForDeploymentPostprocessing = 0;
+ };
+/* End PBXSourcesBuildPhase section */
+
+/* Begin PBXTargetDependency section */
+ 8B9A5ED11831994600A9D33B /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8B9A5EA41831993600A9D33B /* iOSTestHarness */;
+ targetProxy = 8B9A5ED01831994600A9D33B /* PBXContainerItemProxy */;
+ };
+ 8BBEA4BD147C729A00C4ADB7 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 7461B52D0F94FAF800A0C422 /* ProtocolBuffers */;
+ targetProxy = 8BBEA4BC147C729A00C4ADB7 /* PBXContainerItemProxy */;
+ };
+ 8BD3982114BE59EB0081D629 /* PBXTargetDependency */ = {
+ isa = PBXTargetDependency;
+ target = 8BD3981414BE4AE70081D629 /* Compile_Protos */;
+ targetProxy = 8BD3982014BE59EB0081D629 /* PBXContainerItemProxy */;
+ };
+/* End PBXTargetDependency section */
+
+/* Begin PBXVariantGroup section */
+ 8B9A5EAC1831993600A9D33B /* InfoPlist.strings */ = {
+ isa = PBXVariantGroup;
+ children = (
+ 8B9A5EAD1831993600A9D33B /* en */,
+ );
+ name = InfoPlist.strings;
+ sourceTree = "<group>";
+ };
+/* End PBXVariantGroup section */
+
+/* Begin XCBuildConfiguration section */
+ 7461B52F0F94FAFA00A0C422 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = "$(SRCROOT)";
+ PRODUCT_NAME = ProtocolBuffers;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ 7461B5300F94FAFA00A0C422 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = "$(SRCROOT)";
+ PRODUCT_NAME = ProtocolBuffers;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+ 8B9A5ECB1831993600A9D33B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ INFOPLIST_FILE = "$(SRCROOT)/Tests/iOSTestHarness/Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 7.1;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Debug;
+ };
+ 8B9A5ECC1831993600A9D33B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
+ ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage;
+ CLANG_ENABLE_OBJC_ARC = YES;
+ INFOPLIST_FILE = "$(SRCROOT)/Tests/iOSTestHarness/Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 7.1;
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ WRAPPER_EXTENSION = app;
+ };
+ name = Release;
+ };
+ 8BBEA4A7147C727100C4ADB7 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "\"$(SDKROOT)/Developer/Library/Frameworks\"",
+ "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
+ "$(inherited)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "${PROJECT_DERIVED_FILE_DIR}/protos",
+ "$(SRCROOT)",
+ );
+ INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 7.1;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(DEVELOPER_DIR)/usr/lib\"",
+ );
+ PRODUCT_NAME = UnitTests;
+ SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSTestHarness.app/iOSTestHarness";
+ };
+ name = Debug;
+ };
+ 8BBEA4A8147C727100C4ADB7 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ CLANG_ENABLE_MODULES = YES;
+ FRAMEWORK_SEARCH_PATHS = (
+ "\"$(SDKROOT)/Developer/Library/Frameworks\"",
+ "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"",
+ "$(inherited)",
+ );
+ HEADER_SEARCH_PATHS = (
+ "${PROJECT_DERIVED_FILE_DIR}/protos",
+ "$(SRCROOT)",
+ );
+ INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
+ IPHONEOS_DEPLOYMENT_TARGET = 7.1;
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+ LIBRARY_SEARCH_PATHS = (
+ "$(inherited)",
+ "\"$(DEVELOPER_DIR)/usr/lib\"",
+ );
+ PRODUCT_NAME = UnitTests;
+ SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
+ TARGETED_DEVICE_FAMILY = "1,2";
+ TEST_HOST = "$(BUILT_PRODUCTS_DIR)/iOSTestHarness.app/iOSTestHarness";
+ };
+ name = Release;
+ };
+ 8BD3981514BE4AE70081D629 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Debug;
+ };
+ 8BD3981614BE4AE70081D629 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ PRODUCT_NAME = "$(TARGET_NAME)";
+ };
+ name = Release;
+ };
+ C01FCF4F08A954540054247B /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
+ CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
+ CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_OPTIMIZATION_LEVEL = 0;
+ GCC_PREPROCESSOR_DEFINITIONS = "DEBUG=1";
+ GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
+ GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+ GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_PARAMETER = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ GENERATE_PROFILING_CODE = NO;
+ IPHONEOS_DEPLOYMENT_TARGET = 6.1;
+ ONLY_ACTIVE_ARCH = YES;
+ RUN_CLANG_STATIC_ANALYZER = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Debug;
+ };
+ C01FCF5008A954540054247B /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ ALWAYS_SEARCH_USER_PATHS = YES;
+ CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
+ CLANG_ANALYZER_SECURITY_INSECUREAPI_STRCPY = YES;
+ CLANG_STATIC_ANALYZER_MODE = deep;
+ CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
+ CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
+ CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+ CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
+ GCC_C_LANGUAGE_STANDARD = c99;
+ GCC_TREAT_IMPLICIT_FUNCTION_DECLARATIONS_AS_ERRORS = YES;
+ GCC_TREAT_INCOMPATIBLE_POINTER_TYPE_WARNINGS_AS_ERRORS = YES;
+ GCC_TREAT_WARNINGS_AS_ERRORS = YES;
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
+ GCC_WARN_ABOUT_MISSING_FIELD_INITIALIZERS = YES;
+ GCC_WARN_ABOUT_MISSING_NEWLINE = YES;
+ GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES;
+ GCC_WARN_ABOUT_RETURN_TYPE = YES;
+ GCC_WARN_HIDDEN_VIRTUAL_FUNCTIONS = YES;
+ GCC_WARN_INITIALIZER_NOT_FULLY_BRACKETED = YES;
+ GCC_WARN_MISSING_PARENTHESES = YES;
+ GCC_WARN_NON_VIRTUAL_DESTRUCTOR = YES;
+ GCC_WARN_SHADOW = YES;
+ GCC_WARN_SIGN_COMPARE = YES;
+ GCC_WARN_UNDECLARED_SELECTOR = YES;
+ GCC_WARN_UNKNOWN_PRAGMAS = YES;
+ GCC_WARN_UNUSED_FUNCTION = YES;
+ GCC_WARN_UNUSED_LABEL = YES;
+ GCC_WARN_UNUSED_PARAMETER = YES;
+ GCC_WARN_UNUSED_VARIABLE = YES;
+ GENERATE_PROFILING_CODE = NO;
+ IPHONEOS_DEPLOYMENT_TARGET = 6.1;
+ RUN_CLANG_STATIC_ANALYZER = YES;
+ SDKROOT = iphoneos;
+ };
+ name = Release;
+ };
+ F4487C6C1A9F8F8100531423 /* Debug */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = "$(SRCROOT)";
+ PRODUCT_NAME = TestSingleSourceBuild;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Debug;
+ };
+ F4487C6D1A9F8F8100531423 /* Release */ = {
+ isa = XCBuildConfiguration;
+ buildSettings = {
+ HEADER_SEARCH_PATHS = "$(SRCROOT)";
+ PRODUCT_NAME = TestSingleSourceBuild;
+ TARGETED_DEVICE_FAMILY = "1,2";
+ };
+ name = Release;
+ };
+/* End XCBuildConfiguration section */
+
+/* Begin XCConfigurationList section */
+ 7461B5330F94FAFD00A0C422 /* Build configuration list for PBXNativeTarget "ProtocolBuffers" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 7461B52F0F94FAFA00A0C422 /* Debug */,
+ 7461B5300F94FAFA00A0C422 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8B9A5ECA1831993600A9D33B /* Build configuration list for PBXNativeTarget "iOSTestHarness" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8B9A5ECB1831993600A9D33B /* Debug */,
+ 8B9A5ECC1831993600A9D33B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8BBEA4BA147C728600C4ADB7 /* Build configuration list for PBXNativeTarget "UnitTests" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8BBEA4A7147C727100C4ADB7 /* Debug */,
+ 8BBEA4A8147C727100C4ADB7 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ 8BD3981714BE4AE70081D629 /* Build configuration list for PBXAggregateTarget "Compile_Protos" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ 8BD3981514BE4AE70081D629 /* Debug */,
+ 8BD3981614BE4AE70081D629 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_iOS" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ C01FCF4F08A954540054247B /* Debug */,
+ C01FCF5008A954540054247B /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+ F4487C6B1A9F8F8100531423 /* Build configuration list for PBXNativeTarget "TestSingleSourceBuild" */ = {
+ isa = XCConfigurationList;
+ buildConfigurations = (
+ F4487C6C1A9F8F8100531423 /* Debug */,
+ F4487C6D1A9F8F8100531423 /* Release */,
+ );
+ defaultConfigurationIsVisible = 0;
+ defaultConfigurationName = Release;
+ };
+/* End XCConfigurationList section */
+ };
+ rootObject = 29B97313FDCFA39411CA2CEA /* Project object */;
+}
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata
new file mode 100644
index 00000000..037a91df
--- /dev/null
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Workspace
+ version = "1.0">
+ <FileRef
+ location = "self:ProtocolBuffers_iOS.xcodeproj">
+ </FileRef>
+</Workspace>
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
new file mode 100644
index 00000000..08de0be8
--- /dev/null
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>IDEWorkspaceSharedSettings_AutocreateContextsIfNeeded</key>
+ <false/>
+</dict>
+</plist>
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist
new file mode 100644
index 00000000..0ac0943a
--- /dev/null
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/FFE465CA-0E74-40E8-9F09-500B66B7DCB2.plist
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>classNames</key>
+ <dict>
+ <key>PerfTests</key>
+ <dict>
+ <key>testExtensionsPerformance</key>
+ <dict>
+ <key>com.apple.XCTPerformanceMetric_WallClockTime</key>
+ <dict>
+ <key>baselineAverage</key>
+ <real>0.9</real>
+ <key>baselineIntegrationDisplayName</key>
+ <string>Feb 5, 2015, 9:42:41 AM</string>
+ </dict>
+ </dict>
+ <key>testHas</key>
+ <dict>
+ <key>com.apple.XCTPerformanceMetric_WallClockTime</key>
+ <dict>
+ <key>baselineAverage</key>
+ <real>0.09</real>
+ <key>baselineIntegrationDisplayName</key>
+ <string>Feb 5, 2015, 9:42:35 AM</string>
+ </dict>
+ </dict>
+ <key>testMessagePerformance</key>
+ <dict>
+ <key>com.apple.XCTPerformanceMetric_WallClockTime</key>
+ <dict>
+ <key>baselineAverage</key>
+ <real>0.57</real>
+ <key>baselineIntegrationDisplayName</key>
+ <string>Feb 5, 2015, 9:42:47 AM</string>
+ </dict>
+ </dict>
+ <key>testPackedExtensionsPerformance</key>
+ <dict>
+ <key>com.apple.XCTPerformanceMetric_WallClockTime</key>
+ <dict>
+ <key>baselineAverage</key>
+ <real>0.75</real>
+ <key>baselineIntegrationDisplayName</key>
+ <string>Feb 5, 2015, 9:42:51 AM</string>
+ </dict>
+ </dict>
+ <key>testPackedTypesPerformance</key>
+ <dict>
+ <key>com.apple.XCTPerformanceMetric_WallClockTime</key>
+ <dict>
+ <key>baselineAverage</key>
+ <real>0.26</real>
+ <key>baselineIntegrationDisplayName</key>
+ <string>Feb 5, 2015, 9:42:55 AM</string>
+ </dict>
+ </dict>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist
new file mode 100644
index 00000000..45bb9c1b
--- /dev/null
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcbaselines/8BBEA4A5147C727100C4ADB7.xcbaseline/Info.plist
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>runDestinationsByUUID</key>
+ <dict>
+ <key>FFE465CA-0E74-40E8-9F09-500B66B7DCB2</key>
+ <dict>
+ <key>targetArchitecture</key>
+ <string>arm64</string>
+ <key>targetDevice</key>
+ <dict>
+ <key>modelCode</key>
+ <string>iPhone7,1</string>
+ <key>platformIdentifier</key>
+ <string>com.apple.platform.iphoneos</string>
+ </dict>
+ </dict>
+ </dict>
+</dict>
+</plist>
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
new file mode 100644
index 00000000..f5479ba2
--- /dev/null
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
@@ -0,0 +1,134 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0610"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "YES">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Release">
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8BBEA4A5147C727100C4ADB7"
+ BuildableName = "UnitTests.xctest"
+ BlueprintName = "UnitTests"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ <SkippedTests>
+ <Test
+ Identifier = "ArrayTests">
+ </Test>
+ <Test
+ Identifier = "CodedInputStreamTests">
+ </Test>
+ <Test
+ Identifier = "CodedOutputStreamTests">
+ </Test>
+ <Test
+ Identifier = "ConcurrencyTests">
+ </Test>
+ <Test
+ Identifier = "FilteredMessageTests">
+ </Test>
+ <Test
+ Identifier = "GPBStringTests">
+ </Test>
+ <Test
+ Identifier = "GPBTestCase">
+ </Test>
+ <Test
+ Identifier = "GeneratedMessageTests">
+ </Test>
+ <Test
+ Identifier = "MessageTests">
+ </Test>
+ <Test
+ Identifier = "UnknownFieldSetTest">
+ </Test>
+ <Test
+ Identifier = "UtilitiesTests">
+ </Test>
+ <Test
+ Identifier = "WireFormatTests">
+ </Test>
+ </SkippedTests>
+ </TestableReference>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8B9A5EA41831993600A9D33B"
+ BuildableName = "iOSTestHarness.app"
+ BlueprintName = "iOSTestHarness"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8B9A5EA41831993600A9D33B"
+ BuildableName = "iOSTestHarness.app"
+ BlueprintName = "iOSTestHarness"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Release">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
new file mode 100644
index 00000000..a1b4cc45
--- /dev/null
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
@@ -0,0 +1,116 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Scheme
+ LastUpgradeVersion = "0610"
+ version = "1.3">
+ <BuildAction
+ parallelizeBuildables = "YES"
+ buildImplicitDependencies = "NO">
+ <BuildActionEntries>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "YES"
+ buildForArchiving = "YES"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ <BuildActionEntry
+ buildForTesting = "YES"
+ buildForRunning = "YES"
+ buildForProfiling = "NO"
+ buildForArchiving = "NO"
+ buildForAnalyzing = "YES">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "F4487C551A9F8F8100531423"
+ BuildableName = "libTestSingleSourceBuild.a"
+ BlueprintName = "TestSingleSourceBuild"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ </BuildActionEntry>
+ </BuildActionEntries>
+ </BuildAction>
+ <TestAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ buildConfiguration = "Debug">
+ <Testables>
+ <TestableReference
+ skipped = "NO">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8BBEA4A5147C727100C4ADB7"
+ BuildableName = "UnitTests.xctest"
+ BlueprintName = "UnitTests"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ <SkippedTests>
+ <Test
+ Identifier = "PerfTests">
+ </Test>
+ </SkippedTests>
+ </TestableReference>
+ </Testables>
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8B9A5EA41831993600A9D33B"
+ BuildableName = "iOSTestHarness.app"
+ BlueprintName = "iOSTestHarness"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </TestAction>
+ <LaunchAction
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
+ launchStyle = "0"
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Debug"
+ ignoresPersistentStateOnLaunch = "NO"
+ debugDocumentVersioning = "YES"
+ allowLocationSimulation = "YES">
+ <BuildableProductRunnable
+ runnableDebuggingMode = "0">
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "8B9A5EA41831993600A9D33B"
+ BuildableName = "iOSTestHarness.app"
+ BlueprintName = "iOSTestHarness"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ </BuildableProductRunnable>
+ <AdditionalOptions>
+ </AdditionalOptions>
+ </LaunchAction>
+ <ProfileAction
+ shouldUseLaunchSchemeArgsEnv = "YES"
+ savedToolIdentifier = ""
+ useCustomWorkingDirectory = "NO"
+ buildConfiguration = "Release"
+ debugDocumentVersioning = "YES">
+ <MacroExpansion>
+ <BuildableReference
+ BuildableIdentifier = "primary"
+ BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+ BuildableName = "libProtocolBuffers.a"
+ BlueprintName = "ProtocolBuffers"
+ ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
+ </BuildableReference>
+ </MacroExpansion>
+ </ProfileAction>
+ <AnalyzeAction
+ buildConfiguration = "Debug">
+ </AnalyzeAction>
+ <ArchiveAction
+ buildConfiguration = "Release"
+ revealArchiveInOrganizer = "YES">
+ </ArchiveAction>
+</Scheme>
diff --git a/objectivec/Tests/Filter1.txt b/objectivec/Tests/Filter1.txt
new file mode 100644
index 00000000..88a5cac8
--- /dev/null
+++ b/objectivec/Tests/Filter1.txt
@@ -0,0 +1,40 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+
+// Test the filter system for the ObjC Protocol Buffer Compiler.
+
+// Class names are matched using file name globbing rules.
+// Whitespace is not allowed at the beginning of a line (except for a line
+// that is a single newline).
+
+Keep
+RemoveEnumMessage_KeepNestedInside
+RemoveJustKidding
diff --git a/objectivec/Tests/Filter2.txt b/objectivec/Tests/Filter2.txt
new file mode 100644
index 00000000..5a2bb0f8
--- /dev/null
+++ b/objectivec/Tests/Filter2.txt
@@ -0,0 +1,35 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+
+// Test the filter system for the ObjC Protocol Buffer Compiler to test
+// multiple filter support.
+
+Other
diff --git a/objectivec/Tests/GPBARCUnittestProtos.m b/objectivec/Tests/GPBARCUnittestProtos.m
new file mode 100644
index 00000000..daf4effc
--- /dev/null
+++ b/objectivec/Tests/GPBARCUnittestProtos.m
@@ -0,0 +1,57 @@
+#if !defined(__has_feature) || !__has_feature(objc_arc)
+#error "This file requires ARC support."
+#endif
+
+// 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.
+
+// Makes sure all the generated headers compile with ARC on.
+
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestCustomOptions.pbobjc.h"
+#import "google/protobuf/UnittestCycle.pbobjc.h"
+#import "google/protobuf/UnittestDropUnknownFields.pbobjc.h"
+#import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.h"
+#import "google/protobuf/UnittestEmpty.pbobjc.h"
+#import "google/protobuf/UnittestEnormousDescriptor.pbobjc.h"
+#import "google/protobuf/UnittestFilter.pbobjc.h"
+#import "google/protobuf/UnittestImport.pbobjc.h"
+#import "google/protobuf/UnittestImportLite.pbobjc.h"
+#import "google/protobuf/UnittestImportPublic.pbobjc.h"
+#import "google/protobuf/UnittestImportPublicLite.pbobjc.h"
+#import "google/protobuf/UnittestLite.pbobjc.h"
+#import "google/protobuf/UnittestMset.pbobjc.h"
+#import "google/protobuf/UnittestNameMangling.pbobjc.h"
+#import "google/protobuf/UnittestNoGenericServices.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+#import "google/protobuf/UnittestOptimizeFor.pbobjc.h"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
diff --git a/objectivec/Tests/GPBArrayTests.m b/objectivec/Tests/GPBArrayTests.m
new file mode 100644
index 00000000..37724c59
--- /dev/null
+++ b/objectivec/Tests/GPBArrayTests.m
@@ -0,0 +1,3365 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBArray.h"
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBEnumArray (TestingTweak)
++ (instancetype)arrayWithValue:(int32_t)value;
+- (instancetype)initWithValues:(const int32_t [])values
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 71:
+ case 72:
+ case 73:
+ case 74:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+static BOOL TestingEnum_IsValidValue2(int32_t value) {
+ switch (value) {
+ case 71:
+ case 72:
+ case 73:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBEnumArray (TestingTweak)
++ (instancetype)arrayWithValue:(int32_t)value {
+ return [[[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ count:count];
+}
+@end
+
+#pragma mark - PDDM Macros
+
+//%PDDM-DEFINE ARRAY_TESTS(NAME, TYPE, VAL1, VAL2, VAL3, VAL4)
+//%ARRAY_TESTS2(NAME, TYPE, VAL1, VAL2, VAL3, VAL4, )
+//%PDDM-DEFINE ARRAY_TESTS2(NAME, TYPE, VAL1, VAL2, VAL3, VAL4, HELPER)
+//%#pragma mark - NAME
+//%
+//%@interface GPB##NAME##ArrayTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##NAME##ArrayTests
+//%
+//%- (void)testEmpty {
+//% GPB##NAME##Array *array = [[GPB##NAME##Array alloc] init];
+//% XCTAssertNotNil(array);
+//% XCTAssertEqual(array.count, 0U);
+//% XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+//% [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% #pragma unused(value, idx, stop)
+//% XCTFail(@"Shouldn't get here!");
+//% }];
+//% [array enumerateValuesWithOptions:NSEnumerationReverse
+//% usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% #pragma unused(value, idx, stop)
+//% XCTFail(@"Shouldn't get here!");
+//% }];
+//% [array release];
+//%}
+//%
+//%- (void)testOne {
+//% GPB##NAME##Array *array = [GPB##NAME##Array arrayWithValue:VAL1];
+//% XCTAssertNotNil(array);
+//% XCTAssertEqual(array.count, 1U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+//% [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, 0U);
+//% XCTAssertEqual(value, VAL1);
+//% XCTAssertNotEqual(stop, NULL);
+//% }];
+//% [array enumerateValuesWithOptions:NSEnumerationReverse
+//% usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, 0U);
+//% XCTAssertEqual(value, VAL1);
+//% XCTAssertNotEqual(stop, NULL);
+//% }];
+//%}
+//%
+//%- (void)testBasics {
+//% static const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//% XCTAssertEqual(array.count, 4U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertEqual([array valueAtIndex:1], VAL2);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//% XCTAssertEqual([array valueAtIndex:3], VAL4);
+//% XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+//% __block NSUInteger idx2 = 0;
+//% [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, idx2);
+//% XCTAssertEqual(value, kValues[idx]);
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx2;
+//% }];
+//% idx2 = 0;
+//% [array enumerateValuesWithOptions:NSEnumerationReverse
+//% usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, (3 - idx2));
+//% XCTAssertEqual(value, kValues[idx]);
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx2;
+//% }];
+//% // Stopping the enumeration.
+//% idx2 = 0;
+//% [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, idx2);
+//% XCTAssertEqual(value, kValues[idx]);
+//% XCTAssertNotEqual(stop, NULL);
+//% if (idx2 == 1) *stop = YES;
+//% XCTAssertNotEqual(idx, 2U);
+//% XCTAssertNotEqual(idx, 3U);
+//% ++idx2;
+//% }];
+//% idx2 = 0;
+//% [array enumerateValuesWithOptions:NSEnumerationReverse
+//% usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
+//% XCTAssertEqual(idx, (3 - idx2));
+//% XCTAssertEqual(value, kValues[idx]);
+//% XCTAssertNotEqual(stop, NULL);
+//% if (idx2 == 1) *stop = YES;
+//% XCTAssertNotEqual(idx, 1U);
+//% XCTAssertNotEqual(idx, 0U);
+//% ++idx2;
+//% }];
+//% [array release];
+//%}
+//%
+//%- (void)testEquality {
+//% const TYPE kValues1[] = { VAL1, VAL2, VAL3 };
+//% const TYPE kValues2[] = { VAL1, VAL4, VAL3 };
+//% const TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##NAME##Array *array1 =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues1
+//% NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(array1);
+//% GPB##NAME##Array *array1prime =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues1
+//% NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(array1prime);
+//% GPB##NAME##Array *array2 =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues2
+//% NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(array2);
+//% GPB##NAME##Array *array3 =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues3
+//% NAME$S count:GPBARRAYSIZE(kValues3)];
+//% XCTAssertNotNil(array3);
+//%
+//% // 1/1Prime should be different objects, but equal.
+//% XCTAssertNotEqual(array1, array1prime);
+//% XCTAssertEqualObjects(array1, array1prime);
+//% // Equal, so they must have same hash.
+//% XCTAssertEqual([array1 hash], [array1prime hash]);
+//%
+//% // 1/2/3 shouldn't be equal.
+//% XCTAssertNotEqualObjects(array1, array2);
+//% XCTAssertNotEqualObjects(array1, array3);
+//% XCTAssertNotEqualObjects(array2, array3);
+//%
+//% [array1 release];
+//% [array1prime release];
+//% [array2 release];
+//% [array3 release];
+//%}
+//%
+//%- (void)testCopy {
+//% const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//%
+//% GPB##NAME##Array *array2 = [array copy];
+//% XCTAssertNotNil(array2);
+//%
+//% // Should be new object but equal.
+//% XCTAssertNotEqual(array, array2);
+//% XCTAssertEqualObjects(array, array2);
+//%}
+//%
+//%- (void)testArrayFromArray {
+//% const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//%
+//% GPB##NAME##Array *array2 = [GPB##NAME##Array arrayWithValueArray:array];
+//% XCTAssertNotNil(array2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(array, array2);
+//% XCTAssertEqualObjects(array, array2);
+//%}
+//%
+//%- (void)testAdds {
+//% GPB##NAME##Array *array = [GPB##NAME##Array array];
+//% XCTAssertNotNil(array);
+//%
+//% XCTAssertEqual(array.count, 0U);
+//% [array addValue:VAL1];
+//% XCTAssertEqual(array.count, 1U);
+//%
+//% const TYPE kValues1[] = { VAL2, VAL3 };
+//% [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertEqual(array.count, 3U);
+//%
+//% const TYPE kValues2[] = { VAL4, VAL1 };
+//% GPB##NAME##Array *array2 =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues2
+//% NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(array2);
+//% [array add##HELPER##ValuesFromArray:array2];
+//% XCTAssertEqual(array.count, 5U);
+//%
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertEqual([array valueAtIndex:1], VAL2);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//% XCTAssertEqual([array valueAtIndex:3], VAL4);
+//% XCTAssertEqual([array valueAtIndex:4], VAL1);
+//%}
+//%
+//%- (void)testInsert {
+//% const TYPE kValues[] = { VAL1, VAL2, VAL3 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//% XCTAssertEqual(array.count, 3U);
+//%
+//% // First
+//% [array insertValue:VAL4 atIndex:0];
+//% XCTAssertEqual(array.count, 4U);
+//%
+//% // Middle
+//% [array insertValue:VAL4 atIndex:2];
+//% XCTAssertEqual(array.count, 5U);
+//%
+//% // End
+//% [array insertValue:VAL4 atIndex:5];
+//% XCTAssertEqual(array.count, 6U);
+//%
+//% // Too far.
+//% XCTAssertThrowsSpecificNamed([array insertValue:VAL4 atIndex:7],
+//% NSException, NSRangeException);
+//%
+//% XCTAssertEqual([array valueAtIndex:0], VAL4);
+//% XCTAssertEqual([array valueAtIndex:1], VAL1);
+//% XCTAssertEqual([array valueAtIndex:2], VAL4);
+//% XCTAssertEqual([array valueAtIndex:3], VAL2);
+//% XCTAssertEqual([array valueAtIndex:4], VAL3);
+//% XCTAssertEqual([array valueAtIndex:5], VAL4);
+//%}
+//%
+//%- (void)testRemove {
+//% const TYPE kValues[] = { VAL4, VAL1, VAL2, VAL4, VAL3, VAL4 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//% XCTAssertEqual(array.count, 6U);
+//%
+//% // First
+//% [array removeValueAtIndex:0];
+//% XCTAssertEqual(array.count, 5U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//%
+//% // Middle
+//% [array removeValueAtIndex:2];
+//% XCTAssertEqual(array.count, 4U);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//%
+//% // End
+//% [array removeValueAtIndex:3];
+//% XCTAssertEqual(array.count, 3U);
+//%
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertEqual([array valueAtIndex:1], VAL2);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//%
+//% // Too far.
+//% XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+//% NSException, NSRangeException);
+//%
+//% [array removeAll];
+//% XCTAssertEqual(array.count, 0U);
+//% XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+//% NSException, NSRangeException);
+//%}
+//%
+//%- (void)testInplaceMutation {
+//% const TYPE kValues[] = { VAL1, VAL1, VAL3, VAL3 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//%
+//% [array replaceValueAtIndex:1 withValue:VAL2];
+//% [array replaceValueAtIndex:3 withValue:VAL4];
+//% XCTAssertEqual(array.count, 4U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertEqual([array valueAtIndex:1], VAL2);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//% XCTAssertEqual([array valueAtIndex:3], VAL4);
+//%
+//% XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:VAL4],
+//% NSException, NSRangeException);
+//%
+//% [array exchangeValueAtIndex:1 withValueAtIndex:3];
+//% XCTAssertEqual(array.count, 4U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL1);
+//% XCTAssertEqual([array valueAtIndex:1], VAL4);
+//% XCTAssertEqual([array valueAtIndex:2], VAL3);
+//% XCTAssertEqual([array valueAtIndex:3], VAL2);
+//%
+//% [array exchangeValueAtIndex:2 withValueAtIndex:0];
+//% XCTAssertEqual(array.count, 4U);
+//% XCTAssertEqual([array valueAtIndex:0], VAL3);
+//% XCTAssertEqual([array valueAtIndex:1], VAL4);
+//% XCTAssertEqual([array valueAtIndex:2], VAL1);
+//% XCTAssertEqual([array valueAtIndex:3], VAL2);
+//%
+//% XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+//% NSException, NSRangeException);
+//% XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+//% NSException, NSRangeException);
+//%}
+//%
+//%- (void)testInternalResizing {
+//% const TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##NAME##Array *array =
+//% [[GPB##NAME##Array alloc] initWithValues:kValues
+//% NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(array);
+//%
+//% // Add/remove to trigger the intneral buffer to grow/shrink.
+//% for (int i = 0; i < 100; ++i) {
+//% [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+//% }
+//% XCTAssertEqual(array.count, 404U);
+//% for (int i = 0; i < 100; ++i) {
+//% [array removeValueAtIndex:(i * 2)];
+//% }
+//% XCTAssertEqual(array.count, 304U);
+//% for (int i = 0; i < 100; ++i) {
+//% [array insertValue:VAL4 atIndex:(i * 3)];
+//% }
+//% XCTAssertEqual(array.count, 404U);
+//% [array removeAll];
+//% XCTAssertEqual(array.count, 0U);
+//%}
+//%
+//%@end
+//%
+//%PDDM-EXPAND ARRAY_TESTS(Int32, int32_t, 1, 2, 3, 4)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int32
+
+@interface GPBInt32ArrayTests : XCTestCase
+@end
+
+@implementation GPBInt32ArrayTests
+
+- (void)testEmpty {
+ GPBInt32Array *array = [[GPBInt32Array alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBInt32Array *array = [GPBInt32Array arrayWithValue:1];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 1);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 1);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const int32_t kValues[] = { 1, 2, 3, 4 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertEqual([array valueAtIndex:1], 2);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+ XCTAssertEqual([array valueAtIndex:3], 4);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const int32_t kValues1[] = { 1, 2, 3 };
+ const int32_t kValues2[] = { 1, 4, 3 };
+ const int32_t kValues3[] = { 1, 2, 3, 4 };
+ GPBInt32Array *array1 =
+ [[GPBInt32Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBInt32Array *array1prime =
+ [[GPBInt32Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBInt32Array *array2 =
+ [[GPBInt32Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBInt32Array *array3 =
+ [[GPBInt32Array alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const int32_t kValues[] = { 1, 2, 3, 4 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBInt32Array *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const int32_t kValues[] = { 1, 2, 3, 4 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBInt32Array *array2 = [GPBInt32Array arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBInt32Array *array = [GPBInt32Array array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:1];
+ XCTAssertEqual(array.count, 1U);
+
+ const int32_t kValues1[] = { 2, 3 };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const int32_t kValues2[] = { 4, 1 };
+ GPBInt32Array *array2 =
+ [[GPBInt32Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertEqual([array valueAtIndex:1], 2);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+ XCTAssertEqual([array valueAtIndex:3], 4);
+ XCTAssertEqual([array valueAtIndex:4], 1);
+}
+
+- (void)testInsert {
+ const int32_t kValues[] = { 1, 2, 3 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:4 atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:4 atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:4 atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:4 atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 4);
+ XCTAssertEqual([array valueAtIndex:1], 1);
+ XCTAssertEqual([array valueAtIndex:2], 4);
+ XCTAssertEqual([array valueAtIndex:3], 2);
+ XCTAssertEqual([array valueAtIndex:4], 3);
+ XCTAssertEqual([array valueAtIndex:5], 4);
+}
+
+- (void)testRemove {
+ const int32_t kValues[] = { 4, 1, 2, 4, 3, 4 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 1);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertEqual([array valueAtIndex:1], 2);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const int32_t kValues[] = { 1, 1, 3, 3 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:2];
+ [array replaceValueAtIndex:3 withValue:4];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertEqual([array valueAtIndex:1], 2);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+ XCTAssertEqual([array valueAtIndex:3], 4);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:4],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 1);
+ XCTAssertEqual([array valueAtIndex:1], 4);
+ XCTAssertEqual([array valueAtIndex:2], 3);
+ XCTAssertEqual([array valueAtIndex:3], 2);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 3);
+ XCTAssertEqual([array valueAtIndex:1], 4);
+ XCTAssertEqual([array valueAtIndex:2], 1);
+ XCTAssertEqual([array valueAtIndex:3], 2);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const int32_t kValues[] = { 1, 2, 3, 4 };
+ GPBInt32Array *array =
+ [[GPBInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:4 atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(UInt32, uint32_t, 11U, 12U, 13U, 14U)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt32
+
+@interface GPBUInt32ArrayTests : XCTestCase
+@end
+
+@implementation GPBUInt32ArrayTests
+
+- (void)testEmpty {
+ GPBUInt32Array *array = [[GPBUInt32Array alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBUInt32Array *array = [GPBUInt32Array arrayWithValue:11U];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 11U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 11U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertEqual([array valueAtIndex:1], 12U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+ XCTAssertEqual([array valueAtIndex:3], 14U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const uint32_t kValues1[] = { 11U, 12U, 13U };
+ const uint32_t kValues2[] = { 11U, 14U, 13U };
+ const uint32_t kValues3[] = { 11U, 12U, 13U, 14U };
+ GPBUInt32Array *array1 =
+ [[GPBUInt32Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBUInt32Array *array1prime =
+ [[GPBUInt32Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBUInt32Array *array2 =
+ [[GPBUInt32Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBUInt32Array *array3 =
+ [[GPBUInt32Array alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBUInt32Array *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBUInt32Array *array2 = [GPBUInt32Array arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBUInt32Array *array = [GPBUInt32Array array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:11U];
+ XCTAssertEqual(array.count, 1U);
+
+ const uint32_t kValues1[] = { 12U, 13U };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const uint32_t kValues2[] = { 14U, 11U };
+ GPBUInt32Array *array2 =
+ [[GPBUInt32Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertEqual([array valueAtIndex:1], 12U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+ XCTAssertEqual([array valueAtIndex:3], 14U);
+ XCTAssertEqual([array valueAtIndex:4], 11U);
+}
+
+- (void)testInsert {
+ const uint32_t kValues[] = { 11U, 12U, 13U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:14U atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:14U atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:14U atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:14U atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 14U);
+ XCTAssertEqual([array valueAtIndex:1], 11U);
+ XCTAssertEqual([array valueAtIndex:2], 14U);
+ XCTAssertEqual([array valueAtIndex:3], 12U);
+ XCTAssertEqual([array valueAtIndex:4], 13U);
+ XCTAssertEqual([array valueAtIndex:5], 14U);
+}
+
+- (void)testRemove {
+ const uint32_t kValues[] = { 14U, 11U, 12U, 14U, 13U, 14U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertEqual([array valueAtIndex:1], 12U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kValues[] = { 11U, 11U, 13U, 13U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:12U];
+ [array replaceValueAtIndex:3 withValue:14U];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertEqual([array valueAtIndex:1], 12U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+ XCTAssertEqual([array valueAtIndex:3], 14U);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:14U],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 11U);
+ XCTAssertEqual([array valueAtIndex:1], 14U);
+ XCTAssertEqual([array valueAtIndex:2], 13U);
+ XCTAssertEqual([array valueAtIndex:3], 12U);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 13U);
+ XCTAssertEqual([array valueAtIndex:1], 14U);
+ XCTAssertEqual([array valueAtIndex:2], 11U);
+ XCTAssertEqual([array valueAtIndex:3], 12U);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const uint32_t kValues[] = { 11U, 12U, 13U, 14U };
+ GPBUInt32Array *array =
+ [[GPBUInt32Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:14U atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Int64, int64_t, 31LL, 32LL, 33LL, 34LL)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Int64
+
+@interface GPBInt64ArrayTests : XCTestCase
+@end
+
+@implementation GPBInt64ArrayTests
+
+- (void)testEmpty {
+ GPBInt64Array *array = [[GPBInt64Array alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBInt64Array *array = [GPBInt64Array arrayWithValue:31LL];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 31LL);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 31LL);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertEqual([array valueAtIndex:1], 32LL);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+ XCTAssertEqual([array valueAtIndex:3], 34LL);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const int64_t kValues1[] = { 31LL, 32LL, 33LL };
+ const int64_t kValues2[] = { 31LL, 34LL, 33LL };
+ const int64_t kValues3[] = { 31LL, 32LL, 33LL, 34LL };
+ GPBInt64Array *array1 =
+ [[GPBInt64Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBInt64Array *array1prime =
+ [[GPBInt64Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBInt64Array *array2 =
+ [[GPBInt64Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBInt64Array *array3 =
+ [[GPBInt64Array alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBInt64Array *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBInt64Array *array2 = [GPBInt64Array arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBInt64Array *array = [GPBInt64Array array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:31LL];
+ XCTAssertEqual(array.count, 1U);
+
+ const int64_t kValues1[] = { 32LL, 33LL };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const int64_t kValues2[] = { 34LL, 31LL };
+ GPBInt64Array *array2 =
+ [[GPBInt64Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertEqual([array valueAtIndex:1], 32LL);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+ XCTAssertEqual([array valueAtIndex:3], 34LL);
+ XCTAssertEqual([array valueAtIndex:4], 31LL);
+}
+
+- (void)testInsert {
+ const int64_t kValues[] = { 31LL, 32LL, 33LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:34LL atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:34LL atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:34LL atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:34LL atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 34LL);
+ XCTAssertEqual([array valueAtIndex:1], 31LL);
+ XCTAssertEqual([array valueAtIndex:2], 34LL);
+ XCTAssertEqual([array valueAtIndex:3], 32LL);
+ XCTAssertEqual([array valueAtIndex:4], 33LL);
+ XCTAssertEqual([array valueAtIndex:5], 34LL);
+}
+
+- (void)testRemove {
+ const int64_t kValues[] = { 34LL, 31LL, 32LL, 34LL, 33LL, 34LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertEqual([array valueAtIndex:1], 32LL);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const int64_t kValues[] = { 31LL, 31LL, 33LL, 33LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:32LL];
+ [array replaceValueAtIndex:3 withValue:34LL];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertEqual([array valueAtIndex:1], 32LL);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+ XCTAssertEqual([array valueAtIndex:3], 34LL);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:34LL],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 31LL);
+ XCTAssertEqual([array valueAtIndex:1], 34LL);
+ XCTAssertEqual([array valueAtIndex:2], 33LL);
+ XCTAssertEqual([array valueAtIndex:3], 32LL);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 33LL);
+ XCTAssertEqual([array valueAtIndex:1], 34LL);
+ XCTAssertEqual([array valueAtIndex:2], 31LL);
+ XCTAssertEqual([array valueAtIndex:3], 32LL);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const int64_t kValues[] = { 31LL, 32LL, 33LL, 34LL };
+ GPBInt64Array *array =
+ [[GPBInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:34LL atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(UInt64, uint64_t, 41ULL, 42ULL, 43ULL, 44ULL)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - UInt64
+
+@interface GPBUInt64ArrayTests : XCTestCase
+@end
+
+@implementation GPBUInt64ArrayTests
+
+- (void)testEmpty {
+ GPBUInt64Array *array = [[GPBUInt64Array alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBUInt64Array *array = [GPBUInt64Array arrayWithValue:41ULL];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 41ULL);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 41ULL);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertEqual([array valueAtIndex:1], 42ULL);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+ XCTAssertEqual([array valueAtIndex:3], 44ULL);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const uint64_t kValues1[] = { 41ULL, 42ULL, 43ULL };
+ const uint64_t kValues2[] = { 41ULL, 44ULL, 43ULL };
+ const uint64_t kValues3[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array1 =
+ [[GPBUInt64Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBUInt64Array *array1prime =
+ [[GPBUInt64Array alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBUInt64Array *array2 =
+ [[GPBUInt64Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBUInt64Array *array3 =
+ [[GPBUInt64Array alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBUInt64Array *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBUInt64Array *array2 = [GPBUInt64Array arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBUInt64Array *array = [GPBUInt64Array array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:41ULL];
+ XCTAssertEqual(array.count, 1U);
+
+ const uint64_t kValues1[] = { 42ULL, 43ULL };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const uint64_t kValues2[] = { 44ULL, 41ULL };
+ GPBUInt64Array *array2 =
+ [[GPBUInt64Array alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertEqual([array valueAtIndex:1], 42ULL);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+ XCTAssertEqual([array valueAtIndex:3], 44ULL);
+ XCTAssertEqual([array valueAtIndex:4], 41ULL);
+}
+
+- (void)testInsert {
+ const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:44ULL atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:44ULL atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:44ULL atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:44ULL atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 44ULL);
+ XCTAssertEqual([array valueAtIndex:1], 41ULL);
+ XCTAssertEqual([array valueAtIndex:2], 44ULL);
+ XCTAssertEqual([array valueAtIndex:3], 42ULL);
+ XCTAssertEqual([array valueAtIndex:4], 43ULL);
+ XCTAssertEqual([array valueAtIndex:5], 44ULL);
+}
+
+- (void)testRemove {
+ const uint64_t kValues[] = { 44ULL, 41ULL, 42ULL, 44ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertEqual([array valueAtIndex:1], 42ULL);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kValues[] = { 41ULL, 41ULL, 43ULL, 43ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:42ULL];
+ [array replaceValueAtIndex:3 withValue:44ULL];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertEqual([array valueAtIndex:1], 42ULL);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+ XCTAssertEqual([array valueAtIndex:3], 44ULL);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:44ULL],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 41ULL);
+ XCTAssertEqual([array valueAtIndex:1], 44ULL);
+ XCTAssertEqual([array valueAtIndex:2], 43ULL);
+ XCTAssertEqual([array valueAtIndex:3], 42ULL);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 43ULL);
+ XCTAssertEqual([array valueAtIndex:1], 44ULL);
+ XCTAssertEqual([array valueAtIndex:2], 41ULL);
+ XCTAssertEqual([array valueAtIndex:3], 42ULL);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const uint64_t kValues[] = { 41ULL, 42ULL, 43ULL, 44ULL };
+ GPBUInt64Array *array =
+ [[GPBUInt64Array alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:44ULL atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Float, float, 51.f, 52.f, 53.f, 54.f)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Float
+
+@interface GPBFloatArrayTests : XCTestCase
+@end
+
+@implementation GPBFloatArrayTests
+
+- (void)testEmpty {
+ GPBFloatArray *array = [[GPBFloatArray alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBFloatArray *array = [GPBFloatArray arrayWithValue:51.f];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 51.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 51.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertEqual([array valueAtIndex:1], 52.f);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+ XCTAssertEqual([array valueAtIndex:3], 54.f);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const float kValues1[] = { 51.f, 52.f, 53.f };
+ const float kValues2[] = { 51.f, 54.f, 53.f };
+ const float kValues3[] = { 51.f, 52.f, 53.f, 54.f };
+ GPBFloatArray *array1 =
+ [[GPBFloatArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBFloatArray *array1prime =
+ [[GPBFloatArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBFloatArray *array2 =
+ [[GPBFloatArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBFloatArray *array3 =
+ [[GPBFloatArray alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBFloatArray *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBFloatArray *array2 = [GPBFloatArray arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBFloatArray *array = [GPBFloatArray array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:51.f];
+ XCTAssertEqual(array.count, 1U);
+
+ const float kValues1[] = { 52.f, 53.f };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const float kValues2[] = { 54.f, 51.f };
+ GPBFloatArray *array2 =
+ [[GPBFloatArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertEqual([array valueAtIndex:1], 52.f);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+ XCTAssertEqual([array valueAtIndex:3], 54.f);
+ XCTAssertEqual([array valueAtIndex:4], 51.f);
+}
+
+- (void)testInsert {
+ const float kValues[] = { 51.f, 52.f, 53.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:54.f atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:54.f atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:54.f atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:54.f atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 54.f);
+ XCTAssertEqual([array valueAtIndex:1], 51.f);
+ XCTAssertEqual([array valueAtIndex:2], 54.f);
+ XCTAssertEqual([array valueAtIndex:3], 52.f);
+ XCTAssertEqual([array valueAtIndex:4], 53.f);
+ XCTAssertEqual([array valueAtIndex:5], 54.f);
+}
+
+- (void)testRemove {
+ const float kValues[] = { 54.f, 51.f, 52.f, 54.f, 53.f, 54.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertEqual([array valueAtIndex:1], 52.f);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const float kValues[] = { 51.f, 51.f, 53.f, 53.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:52.f];
+ [array replaceValueAtIndex:3 withValue:54.f];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertEqual([array valueAtIndex:1], 52.f);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+ XCTAssertEqual([array valueAtIndex:3], 54.f);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:54.f],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 51.f);
+ XCTAssertEqual([array valueAtIndex:1], 54.f);
+ XCTAssertEqual([array valueAtIndex:2], 53.f);
+ XCTAssertEqual([array valueAtIndex:3], 52.f);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 53.f);
+ XCTAssertEqual([array valueAtIndex:1], 54.f);
+ XCTAssertEqual([array valueAtIndex:2], 51.f);
+ XCTAssertEqual([array valueAtIndex:3], 52.f);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const float kValues[] = { 51.f, 52.f, 53.f, 54.f };
+ GPBFloatArray *array =
+ [[GPBFloatArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:54.f atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Double, double, 61., 62., 63., 64.)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Double
+
+@interface GPBDoubleArrayTests : XCTestCase
+@end
+
+@implementation GPBDoubleArrayTests
+
+- (void)testEmpty {
+ GPBDoubleArray *array = [[GPBDoubleArray alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBDoubleArray *array = [GPBDoubleArray arrayWithValue:61.];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 61.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 61.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const double kValues[] = { 61., 62., 63., 64. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertEqual([array valueAtIndex:1], 62.);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+ XCTAssertEqual([array valueAtIndex:3], 64.);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const double kValues1[] = { 61., 62., 63. };
+ const double kValues2[] = { 61., 64., 63. };
+ const double kValues3[] = { 61., 62., 63., 64. };
+ GPBDoubleArray *array1 =
+ [[GPBDoubleArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBDoubleArray *array1prime =
+ [[GPBDoubleArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBDoubleArray *array2 =
+ [[GPBDoubleArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBDoubleArray *array3 =
+ [[GPBDoubleArray alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const double kValues[] = { 61., 62., 63., 64. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBDoubleArray *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const double kValues[] = { 61., 62., 63., 64. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBDoubleArray *array2 = [GPBDoubleArray arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBDoubleArray *array = [GPBDoubleArray array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:61.];
+ XCTAssertEqual(array.count, 1U);
+
+ const double kValues1[] = { 62., 63. };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const double kValues2[] = { 64., 61. };
+ GPBDoubleArray *array2 =
+ [[GPBDoubleArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertEqual([array valueAtIndex:1], 62.);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+ XCTAssertEqual([array valueAtIndex:3], 64.);
+ XCTAssertEqual([array valueAtIndex:4], 61.);
+}
+
+- (void)testInsert {
+ const double kValues[] = { 61., 62., 63. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:64. atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:64. atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:64. atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:64. atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 64.);
+ XCTAssertEqual([array valueAtIndex:1], 61.);
+ XCTAssertEqual([array valueAtIndex:2], 64.);
+ XCTAssertEqual([array valueAtIndex:3], 62.);
+ XCTAssertEqual([array valueAtIndex:4], 63.);
+ XCTAssertEqual([array valueAtIndex:5], 64.);
+}
+
+- (void)testRemove {
+ const double kValues[] = { 64., 61., 62., 64., 63., 64. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertEqual([array valueAtIndex:1], 62.);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const double kValues[] = { 61., 61., 63., 63. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:62.];
+ [array replaceValueAtIndex:3 withValue:64.];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertEqual([array valueAtIndex:1], 62.);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+ XCTAssertEqual([array valueAtIndex:3], 64.);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:64.],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 61.);
+ XCTAssertEqual([array valueAtIndex:1], 64.);
+ XCTAssertEqual([array valueAtIndex:2], 63.);
+ XCTAssertEqual([array valueAtIndex:3], 62.);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 63.);
+ XCTAssertEqual([array valueAtIndex:1], 64.);
+ XCTAssertEqual([array valueAtIndex:2], 61.);
+ XCTAssertEqual([array valueAtIndex:3], 62.);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const double kValues[] = { 61., 62., 63., 64. };
+ GPBDoubleArray *array =
+ [[GPBDoubleArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:64. atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS(Bool, BOOL, TRUE, TRUE, FALSE, FALSE)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool
+
+@interface GPBBoolArrayTests : XCTestCase
+@end
+
+@implementation GPBBoolArrayTests
+
+- (void)testEmpty {
+ GPBBoolArray *array = [[GPBBoolArray alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBBoolArray *array = [GPBBoolArray arrayWithValue:TRUE];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, TRUE);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, TRUE);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertEqual([array valueAtIndex:1], TRUE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+ XCTAssertEqual([array valueAtIndex:3], FALSE);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const BOOL kValues1[] = { TRUE, TRUE, FALSE };
+ const BOOL kValues2[] = { TRUE, FALSE, FALSE };
+ const BOOL kValues3[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array1 =
+ [[GPBBoolArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBBoolArray *array1prime =
+ [[GPBBoolArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBBoolArray *array2 =
+ [[GPBBoolArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBBoolArray *array3 =
+ [[GPBBoolArray alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBBoolArray *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBBoolArray *array2 = [GPBBoolArray arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBBoolArray *array = [GPBBoolArray array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:TRUE];
+ XCTAssertEqual(array.count, 1U);
+
+ const BOOL kValues1[] = { TRUE, FALSE };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const BOOL kValues2[] = { FALSE, TRUE };
+ GPBBoolArray *array2 =
+ [[GPBBoolArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertEqual([array valueAtIndex:1], TRUE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+ XCTAssertEqual([array valueAtIndex:3], FALSE);
+ XCTAssertEqual([array valueAtIndex:4], TRUE);
+}
+
+- (void)testInsert {
+ const BOOL kValues[] = { TRUE, TRUE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:FALSE atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:FALSE atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:FALSE atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:FALSE atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], FALSE);
+ XCTAssertEqual([array valueAtIndex:1], TRUE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+ XCTAssertEqual([array valueAtIndex:3], TRUE);
+ XCTAssertEqual([array valueAtIndex:4], FALSE);
+ XCTAssertEqual([array valueAtIndex:5], FALSE);
+}
+
+- (void)testRemove {
+ const BOOL kValues[] = { FALSE, TRUE, TRUE, FALSE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertEqual([array valueAtIndex:1], TRUE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:TRUE];
+ [array replaceValueAtIndex:3 withValue:FALSE];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertEqual([array valueAtIndex:1], TRUE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+ XCTAssertEqual([array valueAtIndex:3], FALSE);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:FALSE],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], TRUE);
+ XCTAssertEqual([array valueAtIndex:1], FALSE);
+ XCTAssertEqual([array valueAtIndex:2], FALSE);
+ XCTAssertEqual([array valueAtIndex:3], TRUE);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], FALSE);
+ XCTAssertEqual([array valueAtIndex:1], FALSE);
+ XCTAssertEqual([array valueAtIndex:2], TRUE);
+ XCTAssertEqual([array valueAtIndex:3], TRUE);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const BOOL kValues[] = { TRUE, TRUE, FALSE, FALSE };
+ GPBBoolArray *array =
+ [[GPBBoolArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:FALSE atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND ARRAY_TESTS2(Enum, int32_t, 71, 72, 73, 74, Raw)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Enum
+
+@interface GPBEnumArrayTests : XCTestCase
+@end
+
+@implementation GPBEnumArrayTests
+
+- (void)testEmpty {
+ GPBEnumArray *array = [[GPBEnumArray alloc] init];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ #pragma unused(value, idx, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [array release];
+}
+
+- (void)testOne {
+ GPBEnumArray *array = [GPBEnumArray arrayWithValue:71];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 1U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:1], NSException, NSRangeException);
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 71);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, 0U);
+ XCTAssertEqual(value, 71);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ static const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 72);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+ XCTAssertEqual([array valueAtIndex:3], 74);
+ XCTAssertThrowsSpecificNamed([array valueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const int32_t kValues1[] = { 71, 72, 73 };
+ const int32_t kValues2[] = { 71, 74, 73 };
+ const int32_t kValues3[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array1 =
+ [[GPBEnumArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBEnumArray *array1prime =
+ [[GPBEnumArray alloc] initWithValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBEnumArray *array2 =
+ [[GPBEnumArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBEnumArray *array3 =
+ [[GPBEnumArray alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBEnumArray *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testArrayFromArray {
+ const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBEnumArray *array2 = [GPBEnumArray arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+}
+
+- (void)testAdds {
+ GPBEnumArray *array = [GPBEnumArray array];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addValue:71];
+ XCTAssertEqual(array.count, 1U);
+
+ const int32_t kValues1[] = { 72, 73 };
+ [array addValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const int32_t kValues2[] = { 74, 71 };
+ GPBEnumArray *array2 =
+ [[GPBEnumArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addRawValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 72);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+ XCTAssertEqual([array valueAtIndex:3], 74);
+ XCTAssertEqual([array valueAtIndex:4], 71);
+}
+
+- (void)testInsert {
+ const int32_t kValues[] = { 71, 72, 73 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertValue:74 atIndex:0];
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertValue:74 atIndex:2];
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertValue:74 atIndex:5];
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertValue:74 atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array valueAtIndex:0], 74);
+ XCTAssertEqual([array valueAtIndex:1], 71);
+ XCTAssertEqual([array valueAtIndex:2], 74);
+ XCTAssertEqual([array valueAtIndex:3], 72);
+ XCTAssertEqual([array valueAtIndex:4], 73);
+ XCTAssertEqual([array valueAtIndex:5], 74);
+}
+
+- (void)testRemove {
+ const int32_t kValues[] = { 74, 71, 72, 74, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 6U);
+
+ // First
+ [array removeValueAtIndex:0];
+ XCTAssertEqual(array.count, 5U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+
+ // Middle
+ [array removeValueAtIndex:2];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+
+ // End
+ [array removeValueAtIndex:3];
+ XCTAssertEqual(array.count, 3U);
+
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 72);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:3],
+ NSException, NSRangeException);
+
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+ XCTAssertThrowsSpecificNamed([array removeValueAtIndex:0],
+ NSException, NSRangeException);
+}
+
+- (void)testInplaceMutation {
+ const int32_t kValues[] = { 71, 71, 73, 73 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withValue:72];
+ [array replaceValueAtIndex:3 withValue:74];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 72);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+ XCTAssertEqual([array valueAtIndex:3], 74);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withValue:74],
+ NSException, NSRangeException);
+
+ [array exchangeValueAtIndex:1 withValueAtIndex:3];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 74);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+ XCTAssertEqual([array valueAtIndex:3], 72);
+
+ [array exchangeValueAtIndex:2 withValueAtIndex:0];
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 73);
+ XCTAssertEqual([array valueAtIndex:1], 74);
+ XCTAssertEqual([array valueAtIndex:2], 71);
+ XCTAssertEqual([array valueAtIndex:3], 72);
+
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:4 withValueAtIndex:1],
+ NSException, NSRangeException);
+ XCTAssertThrowsSpecificNamed([array exchangeValueAtIndex:1 withValueAtIndex:4],
+ NSException, NSRangeException);
+}
+
+- (void)testInternalResizing {
+ const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertValue:74 atIndex:(i * 3)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
+
+//%PDDM-EXPAND-END (8 expansions)
+
+#pragma mark - Non macro-based Enum tests
+
+// These are hand written tests to cover the verification and raw methods.
+
+@interface GPBEnumArrayCustomTests : XCTestCase
+@end
+
+@implementation GPBEnumArrayCustomTests
+
+- (void)testRawBasics {
+ static const int32_t kValues[] = { 71, 272, 73, 374 };
+ static const int32_t kValuesFiltered[] = {
+ 71, kGPBUnrecognizedEnumeratorValue, 73, kGPBUnrecognizedEnumeratorValue
+ };
+ XCTAssertEqual(GPBARRAYSIZE(kValues), GPBARRAYSIZE(kValuesFiltered));
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 4U);
+ GPBEnumValidationFunc func = TestingEnum_IsValidValue;
+ XCTAssertEqual(array.validationFunc, func);
+ XCTAssertEqual([array rawValueAtIndex:0], 71);
+ XCTAssertEqual([array rawValueAtIndex:1], 272);
+ XCTAssertEqual([array valueAtIndex:1], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:2], 73);
+ XCTAssertEqual([array rawValueAtIndex:3], 374);
+ XCTAssertEqual([array valueAtIndex:3], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertThrowsSpecificNamed([array rawValueAtIndex:4], NSException, NSRangeException);
+ __block NSUInteger idx2 = 0;
+ [array enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValuesFiltered[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateRawValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValuesFiltered[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ ++idx2;
+ }];
+ // Stopping the enumeration.
+ idx2 = 0;
+ [array enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, idx2);
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ XCTAssertNotEqual(idx, 3U);
+ ++idx2;
+ }];
+ idx2 = 0;
+ [array enumerateRawValuesWithOptions:NSEnumerationReverse
+ usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
+ XCTAssertEqual(idx, (3 - idx2));
+ XCTAssertEqual(value, kValues[idx]);
+ XCTAssertNotEqual(stop, NULL);
+ if (idx2 == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 1U);
+ XCTAssertNotEqual(idx, 0U);
+ ++idx2;
+ }];
+ [array release];
+}
+
+- (void)testEquality {
+ const int32_t kValues1[] = { 71, 72, 173 }; // With unknown value
+ const int32_t kValues2[] = { 71, 74, 173 }; // With unknown value
+ const int32_t kValues3[] = { 71, 72, 173, 74 }; // With unknown value
+ GPBEnumArray *array1 =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1);
+ GPBEnumArray *array1prime =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue2
+ rawValues:kValues1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(array1prime);
+ GPBEnumArray *array2 =
+ [[GPBEnumArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ GPBEnumArray *array3 =
+ [[GPBEnumArray alloc] initWithValues:kValues3
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(array3);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(array1, array1prime);
+ XCTAssertEqualObjects(array1, array1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([array1 hash], [array1prime hash]);
+ // But different validation functions.
+ XCTAssertNotEqual(array1.validationFunc, array1prime.validationFunc);
+
+ // 1/2/3 shouldn't be equal.
+ XCTAssertNotEqualObjects(array1, array2);
+ XCTAssertNotEqualObjects(array1, array3);
+ XCTAssertNotEqualObjects(array2, array3);
+
+ [array1 release];
+ [array1prime release];
+ [array2 release];
+ [array3 release];
+}
+
+- (void)testCopy {
+ const int32_t kValues[] = { 71, 72 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array addRawValue:1000]; // Unknown
+ XCTAssertEqual(array.count, 3U);
+ XCTAssertEqual([array rawValueAtIndex:0], 71);
+ XCTAssertEqual([array rawValueAtIndex:1], 72);
+ XCTAssertEqual([array rawValueAtIndex:2], 1000);
+ XCTAssertEqual([array valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+
+ GPBEnumArray *array2 = [array copy];
+ XCTAssertNotNil(array2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+ XCTAssertEqual(array.validationFunc, array2.validationFunc);
+ XCTAssertTrue([array2 isKindOfClass:[GPBEnumArray class]]);
+ XCTAssertEqual(array2.count, 3U);
+ XCTAssertEqual([array2 rawValueAtIndex:0], 71);
+ XCTAssertEqual([array2 rawValueAtIndex:1], 72);
+ XCTAssertEqual([array2 rawValueAtIndex:2], 1000);
+ XCTAssertEqual([array2 valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+}
+
+- (void)testArrayFromArray {
+ const int32_t kValues[] = { 71, 172, 173, 74 }; // Unknowns
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ GPBEnumArray *array2 = [GPBEnumArray arrayWithValueArray:array];
+ XCTAssertNotNil(array2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(array, array2);
+ XCTAssertEqualObjects(array, array2);
+ XCTAssertEqual(array.validationFunc, array2.validationFunc);
+}
+
+- (void)testUnknownAdds {
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(array);
+
+ XCTAssertThrowsSpecificNamed([array addValue:172],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 0U);
+
+ const int32_t kValues1[] = { 172, 173 }; // Unknown
+ XCTAssertThrowsSpecificNamed([array addValues:kValues1 count:GPBARRAYSIZE(kValues1)],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 0U);
+
+ [array release];
+}
+
+- (void)testRawAdds {
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(array);
+
+ XCTAssertEqual(array.count, 0U);
+ [array addRawValue:71]; // Valid
+ XCTAssertEqual(array.count, 1U);
+
+ const int32_t kValues1[] = { 172, 173 }; // Unknown
+ [array addRawValues:kValues1 count:GPBARRAYSIZE(kValues1)];
+ XCTAssertEqual(array.count, 3U);
+
+ const int32_t kValues2[] = { 74, 71 };
+ GPBEnumArray *array2 =
+ [[GPBEnumArray alloc] initWithValues:kValues2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(array2);
+ [array addRawValuesFromArray:array2];
+ XCTAssertEqual(array.count, 5U);
+
+ XCTAssertEqual([array rawValueAtIndex:0], 71);
+ XCTAssertEqual([array rawValueAtIndex:1], 172);
+ XCTAssertEqual([array valueAtIndex:1], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:2], 173);
+ XCTAssertEqual([array valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:3], 74);
+ XCTAssertEqual([array rawValueAtIndex:4], 71);
+
+ [array release];
+}
+
+- (void)testUnknownInserts {
+ const int32_t kValues[] = { 71, 72, 73 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ XCTAssertThrowsSpecificNamed([array insertValue:174 atIndex:0],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 3U);
+
+ // Middle
+ XCTAssertThrowsSpecificNamed([array insertValue:274 atIndex:1],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 3U);
+
+ // End
+ XCTAssertThrowsSpecificNamed([array insertValue:374 atIndex:3],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 3U);
+}
+
+- (void)testRawInsert {
+ const int32_t kValues[] = { 71, 72, 73 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+ XCTAssertEqual(array.count, 3U);
+
+ // First
+ [array insertRawValue:174 atIndex:0]; // Unknown
+ XCTAssertEqual(array.count, 4U);
+
+ // Middle
+ [array insertRawValue:274 atIndex:2]; // Unknown
+ XCTAssertEqual(array.count, 5U);
+
+ // End
+ [array insertRawValue:374 atIndex:5]; // Unknown
+ XCTAssertEqual(array.count, 6U);
+
+ // Too far.
+ XCTAssertThrowsSpecificNamed([array insertRawValue:74 atIndex:7],
+ NSException, NSRangeException);
+
+ XCTAssertEqual([array rawValueAtIndex:0], 174);
+ XCTAssertEqual([array valueAtIndex:0], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:1], 71);
+ XCTAssertEqual([array rawValueAtIndex:2], 274);
+ XCTAssertEqual([array valueAtIndex:2], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:3], 72);
+ XCTAssertEqual([array rawValueAtIndex:4], 73);
+ XCTAssertEqual([array rawValueAtIndex:5], 374);
+ XCTAssertEqual([array valueAtIndex:5], kGPBUnrecognizedEnumeratorValue);
+
+ [array release];
+}
+
+- (void)testUnknownInplaceMutation {
+ const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:1 withValue:172],
+ NSException, NSInvalidArgumentException);
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:3 withValue:274],
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array valueAtIndex:0], 71);
+ XCTAssertEqual([array valueAtIndex:1], 72);
+ XCTAssertEqual([array valueAtIndex:2], 73);
+ XCTAssertEqual([array valueAtIndex:3], 74);
+}
+
+
+- (void)testRawInplaceMutation {
+ const int32_t kValues[] = { 71, 72, 73, 74 };
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ [array replaceValueAtIndex:1 withRawValue:172]; // Unknown
+ [array replaceValueAtIndex:3 withRawValue:274]; // Unknown
+ XCTAssertEqual(array.count, 4U);
+ XCTAssertEqual([array rawValueAtIndex:0], 71);
+ XCTAssertEqual([array rawValueAtIndex:1], 172);
+ XCTAssertEqual([array valueAtIndex:1], kGPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([array rawValueAtIndex:2], 73);
+ XCTAssertEqual([array rawValueAtIndex:3], 274);
+ XCTAssertEqual([array valueAtIndex:3], kGPBUnrecognizedEnumeratorValue);
+
+ XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withRawValue:74],
+ NSException, NSRangeException);
+}
+
+- (void)testRawInternalResizing {
+ const int32_t kValues[] = { 71, 172, 173, 74 }; // Unknown
+ GPBEnumArray *array =
+ [[GPBEnumArray alloc] initWithValues:kValues
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(array);
+
+ // Add/remove to trigger the intneral buffer to grow/shrink.
+ for (int i = 0; i < 100; ++i) {
+ [array addRawValues:kValues count:GPBARRAYSIZE(kValues)];
+ }
+ XCTAssertEqual(array.count, 404U);
+ for (int i = 0; i < 100; ++i) {
+ [array removeValueAtIndex:(i * 2)];
+ }
+ XCTAssertEqual(array.count, 304U);
+ for (int i = 0; i < 100; ++i) {
+ [array insertRawValue:274 atIndex:(i * 3)]; // Unknown
+ }
+ XCTAssertEqual(array.count, 404U);
+ [array removeAll];
+ XCTAssertEqual(array.count, 0U);
+}
+
+@end
diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m
new file mode 100644
index 00000000..0a709cbe
--- /dev/null
+++ b/objectivec/Tests/GPBCodedInputStreamTests.m
@@ -0,0 +1,290 @@
+// 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 "GPBTestUtilities.h"
+
+#import "GPBCodedInputStream.h"
+#import "GPBCodedOutputStream.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "GPBUtilities_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface CodedInputStreamTests : GPBTestCase
+@end
+
+@implementation CodedInputStreamTests
+
+- (NSData*)bytes_with_sentinel:(int32_t)unused, ... {
+ va_list list;
+ va_start(list, unused);
+
+ NSMutableData* values = [NSMutableData dataWithCapacity:0];
+ int32_t i;
+
+ while ((i = va_arg(list, int32_t)) != 256) {
+ NSAssert(i >= 0 && i < 256, @"");
+ uint8_t u = (uint8_t)i;
+ [values appendBytes:&u length:1];
+ }
+
+ va_end(list);
+
+ return values;
+}
+
+#define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256]
+
+- (void)testDecodeZigZag {
+ XCTAssertEqual(0, GPBDecodeZigZag32(0));
+ XCTAssertEqual(-1, GPBDecodeZigZag32(1));
+ XCTAssertEqual(1, GPBDecodeZigZag32(2));
+ XCTAssertEqual(-2, GPBDecodeZigZag32(3));
+ XCTAssertEqual((int32_t)0x3FFFFFFF, GPBDecodeZigZag32(0x7FFFFFFE));
+ XCTAssertEqual((int32_t)0xC0000000, GPBDecodeZigZag32(0x7FFFFFFF));
+ XCTAssertEqual((int32_t)0x7FFFFFFF, GPBDecodeZigZag32(0xFFFFFFFE));
+ XCTAssertEqual((int32_t)0x80000000, GPBDecodeZigZag32(0xFFFFFFFF));
+
+ XCTAssertEqual((int64_t)0, GPBDecodeZigZag64(0));
+ XCTAssertEqual((int64_t)-1, GPBDecodeZigZag64(1));
+ XCTAssertEqual((int64_t)1, GPBDecodeZigZag64(2));
+ XCTAssertEqual((int64_t)-2, GPBDecodeZigZag64(3));
+ XCTAssertEqual((int64_t)0x000000003FFFFFFFL,
+ GPBDecodeZigZag64(0x000000007FFFFFFEL));
+ XCTAssertEqual((int64_t)0xFFFFFFFFC0000000L,
+ GPBDecodeZigZag64(0x000000007FFFFFFFL));
+ XCTAssertEqual((int64_t)0x000000007FFFFFFFL,
+ GPBDecodeZigZag64(0x00000000FFFFFFFEL));
+ XCTAssertEqual((int64_t)0xFFFFFFFF80000000L,
+ GPBDecodeZigZag64(0x00000000FFFFFFFFL));
+ XCTAssertEqual((int64_t)0x7FFFFFFFFFFFFFFFL,
+ GPBDecodeZigZag64(0xFFFFFFFFFFFFFFFEL));
+ XCTAssertEqual((int64_t)0x8000000000000000L,
+ GPBDecodeZigZag64(0xFFFFFFFFFFFFFFFFL));
+}
+
+- (void)assertReadVarint:(NSData*)data value:(int64_t)value {
+ {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertEqual((int32_t)value, [input readInt32]);
+ }
+ {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertEqual(value, [input readInt64]);
+ }
+}
+
+- (void)assertReadLittleEndian32:(NSData*)data value:(int32_t)value {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertEqual(value, [input readSFixed32]);
+}
+
+- (void)assertReadLittleEndian64:(NSData*)data value:(int64_t)value {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertEqual(value, [input readSFixed64]);
+}
+
+- (void)assertReadVarintFailure:(NSData*)data {
+ {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertThrows([input readInt32]);
+ }
+ {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ XCTAssertThrows([input readInt64]);
+ }
+}
+
+- (void)testBytes {
+ NSData* data = bytes(0xa2, 0x74);
+ XCTAssertEqual(data.length, (NSUInteger)2);
+ XCTAssertEqual(((uint8_t*)data.bytes)[0], (uint8_t)0xa2);
+ XCTAssertEqual(((uint8_t*)data.bytes)[1], (uint8_t)0x74);
+}
+
+- (void)testReadVarint {
+ [self assertReadVarint:bytes(0x00) value:0];
+ [self assertReadVarint:bytes(0x01) value:1];
+ [self assertReadVarint:bytes(0x7f) value:127];
+ // 14882
+ [self assertReadVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)];
+ // 2961488830
+ [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
+ value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+ (0x04 << 21) | (0x0bLL << 28)];
+
+ // 64-bit
+ // 7256456126
+ [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b)
+ value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+ (0x04 << 21) | (0x1bLL << 28)];
+ // 41256202580718336
+ [self assertReadVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49)
+ value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) |
+ (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) |
+ (0x24LL << 42) | (0x49LL << 49)];
+ // 11964378330978735131
+ [self
+ assertReadVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85,
+ 0xa6, 0x01)
+ value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
+ (0x3bLL << 28) | (0x56LL << 35) | (0x00LL << 42) |
+ (0x05LL << 49) | (0x26LL << 56) | (0x01LL << 63)];
+
+ // Failures
+ [self assertReadVarintFailure:bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+ 0x80, 0x80, 0x80, 0x00)];
+ [self assertReadVarintFailure:bytes(0x80)];
+}
+
+- (void)testReadLittleEndian {
+ [self assertReadLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
+ value:0x12345678];
+ [self assertReadLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a)
+ value:0x9abcdef0];
+
+ [self assertReadLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34,
+ 0x12)
+ value:0x123456789abcdef0LL];
+ [self assertReadLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc,
+ 0x9a)
+ value:0x9abcdef012345678LL];
+}
+
+- (void)testReadWholeMessage {
+ TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+
+ NSData* rawBytes = message.data;
+ XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+ TestAllTypes* message2 =
+ [TestAllTypes parseFromData:rawBytes extensionRegistry:nil];
+ [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSkipWholeMessage {
+ TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes = message.data;
+
+ // Create two parallel inputs. Parse one as unknown fields while using
+ // skipField() to skip each field on the other. Expect the same tags.
+ GPBCodedInputStream* input1 = [GPBCodedInputStream streamWithData:rawBytes];
+ GPBCodedInputStream* input2 = [GPBCodedInputStream streamWithData:rawBytes];
+ GPBUnknownFieldSet* unknownFields =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+
+ while (YES) {
+ int32_t tag = [input1 readTag];
+ XCTAssertEqual(tag, [input2 readTag]);
+ if (tag == 0) {
+ break;
+ }
+ [unknownFields mergeFieldFrom:tag input:input1];
+ [input2 skipField:tag];
+ }
+}
+
+- (void)testReadHugeBlob {
+ // Allocate and initialize a 1MB blob.
+ NSMutableData* blob = [NSMutableData dataWithLength:1 << 20];
+ for (NSUInteger i = 0; i < blob.length; i++) {
+ ((uint8_t*)blob.mutableBytes)[i] = (uint8_t)i;
+ }
+
+ // Make a message containing it.
+ TestAllTypes* message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [message setOptionalBytes:blob];
+
+ // Serialize and parse it. Make sure to parse from an InputStream, not
+ // directly from a ByteString, so that CodedInputStream uses buffered
+ // reading.
+ GPBCodedInputStream* stream =
+ [GPBCodedInputStream streamWithData:message.data];
+ TestAllTypes* message2 =
+ [TestAllTypes parseFromCodedInputStream:stream extensionRegistry:nil];
+
+ XCTAssertEqualObjects(message.optionalBytes, message2.optionalBytes);
+
+ // Make sure all the other fields were parsed correctly.
+ TestAllTypes* message3 = [[message2 copy] autorelease];
+ TestAllTypes* types = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* data = [types optionalBytes];
+ [message3 setOptionalBytes:data];
+
+ [self assertAllFieldsSet:message3 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testReadMaliciouslyLargeBlob {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+
+ int32_t tag = GPBWireFormatMakeTag(1, GPBWireFormatLengthDelimited);
+ [output writeRawVarint32:tag];
+ [output writeRawVarint32:0x7FFFFFFF];
+ uint8_t bytes[32] = {0};
+ [output writeRawData:[NSData dataWithBytes:bytes length:32]];
+ [output flush];
+
+ NSData* data =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ GPBCodedInputStream* input =
+ [GPBCodedInputStream streamWithData:[NSMutableData dataWithData:data]];
+ XCTAssertEqual(tag, [input readTag]);
+
+ XCTAssertThrows([input readData]);
+}
+
+// Verifies fix for b/10315336.
+- (void)testReadMalformedString {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+
+ int32_t tag = GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString,
+ GPBWireFormatLengthDelimited);
+ [output writeRawVarint32:tag];
+ [output writeRawVarint32:5];
+ // Create an invalid utf-8 byte array.
+ uint8_t bytes[5] = {0xc2, 0xf2};
+ [output writeRawData:[NSData dataWithBytes:bytes length:sizeof(bytes)]];
+ [output flush];
+
+ NSData* data =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ TestAllTypes* message =
+ [TestAllTypes parseFromCodedInputStream:input extensionRegistry:nil];
+ // Make sure we can read string properties twice without crashing.
+ XCTAssertEqual([message.defaultString length], (NSUInteger)0);
+ XCTAssertEqualObjects(@"", message.defaultString);
+}
+
+@end
diff --git a/objectivec/Tests/GPBCodedOuputStreamTests.m b/objectivec/Tests/GPBCodedOuputStreamTests.m
new file mode 100644
index 00000000..77d88033
--- /dev/null
+++ b/objectivec/Tests/GPBCodedOuputStreamTests.m
@@ -0,0 +1,321 @@
+// 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 "GPBTestUtilities.h"
+
+#import "GPBCodedOutputStream.h"
+#import "GPBCodedInputStream.h"
+#import "GPBUtilities_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface CodedOutputStreamTests : GPBTestCase
+@end
+
+@implementation CodedOutputStreamTests
+
+- (NSData*)bytes_with_sentinel:(int32_t)unused, ... {
+ va_list list;
+ va_start(list, unused);
+
+ NSMutableData* values = [NSMutableData dataWithCapacity:0];
+ int32_t i;
+
+ while ((i = va_arg(list, int32_t)) != 256) {
+ NSAssert(i >= 0 && i < 256, @"");
+ uint8_t u = (uint8_t)i;
+ [values appendBytes:&u length:1];
+ }
+
+ va_end(list);
+
+ return values;
+}
+
+#define bytes(...) [self bytes_with_sentinel:0, __VA_ARGS__, 256]
+
+- (void)assertWriteLittleEndian32:(NSData*)data value:(int32_t)value {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+ [output writeRawLittleEndian32:(int32_t)value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ rawOutput = [NSOutputStream outputStreamToMemory];
+ output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+ [output writeRawLittleEndian32:(int32_t)value];
+ [output flush];
+
+ actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+ }
+}
+
+- (void)assertWriteLittleEndian64:(NSData*)data value:(int64_t)value {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+ [output writeRawLittleEndian64:value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ rawOutput = [NSOutputStream outputStreamToMemory];
+ output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+ [output writeRawLittleEndian64:value];
+ [output flush];
+
+ actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+ }
+}
+
+- (void)assertWriteVarint:(NSData*)data value:(int64_t)value {
+ // Only do 32-bit write if the value fits in 32 bits.
+ if (GPBLogicalRightShift64(value, 32) == 0) {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+ [output writeRawVarint32:(int32_t)value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+
+ // Also try computing size.
+ XCTAssertEqual(GPBComputeRawVarint32Size((int32_t)value),
+ (size_t)data.length);
+ }
+
+ {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+ [output writeRawVarint64:value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+
+ // Also try computing size.
+ XCTAssertEqual(GPBComputeRawVarint64Size(value), (size_t)data.length);
+ }
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
+ // Only do 32-bit write if the value fits in 32 bits.
+ if (GPBLogicalRightShift64(value, 32) == 0) {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+
+ [output writeRawVarint32:(int32_t)value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+ }
+
+ {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+
+ [output writeRawVarint64:value];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(data, actual);
+ }
+ }
+}
+
+- (void)testWriteVarint1 {
+ [self assertWriteVarint:bytes(0x00) value:0];
+}
+
+- (void)testWriteVarint2 {
+ [self assertWriteVarint:bytes(0x01) value:1];
+}
+
+- (void)testWriteVarint3 {
+ [self assertWriteVarint:bytes(0x7f) value:127];
+}
+
+- (void)testWriteVarint4 {
+ // 14882
+ [self assertWriteVarint:bytes(0xa2, 0x74) value:(0x22 << 0) | (0x74 << 7)];
+}
+
+- (void)testWriteVarint5 {
+ // 2961488830
+ [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
+ value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+ (0x04 << 21) | (0x0bLL << 28)];
+}
+
+- (void)testWriteVarint6 {
+ // 64-bit
+ // 7256456126
+ [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b)
+ value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
+ (0x04 << 21) | (0x1bLL << 28)];
+}
+
+- (void)testWriteVarint7 {
+ // 41256202580718336
+ [self assertWriteVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49)
+ value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) |
+ (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) |
+ (0x24LL << 42) | (0x49LL << 49)];
+}
+
+- (void)testWriteVarint8 {
+ // 11964378330978735131
+ [self assertWriteVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85,
+ 0xa6, 0x01)
+ value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) |
+ (0x42 << 21) | (0x3bLL << 28) | (0x56LL << 35) |
+ (0x00LL << 42) | (0x05LL << 49) | (0x26LL << 56) |
+ (0x01LL << 63)];
+}
+
+- (void)testWriteLittleEndian {
+ [self assertWriteLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
+ value:0x12345678];
+ [self assertWriteLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a)
+ value:0x9abcdef0];
+
+ [self assertWriteLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
+ 0x34, 0x12)
+ value:0x123456789abcdef0LL];
+ [self assertWriteLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde,
+ 0xbc, 0x9a)
+ value:0x9abcdef012345678LL];
+}
+
+- (void)testEncodeZigZag {
+ XCTAssertEqual(0U, GPBEncodeZigZag32(0));
+ XCTAssertEqual(1U, GPBEncodeZigZag32(-1));
+ XCTAssertEqual(2U, GPBEncodeZigZag32(1));
+ XCTAssertEqual(3U, GPBEncodeZigZag32(-2));
+ XCTAssertEqual(0x7FFFFFFEU, GPBEncodeZigZag32(0x3FFFFFFF));
+ XCTAssertEqual(0x7FFFFFFFU, GPBEncodeZigZag32(0xC0000000));
+ XCTAssertEqual(0xFFFFFFFEU, GPBEncodeZigZag32(0x7FFFFFFF));
+ XCTAssertEqual(0xFFFFFFFFU, GPBEncodeZigZag32(0x80000000));
+
+ XCTAssertEqual(0ULL, GPBEncodeZigZag64(0));
+ XCTAssertEqual(1ULL, GPBEncodeZigZag64(-1));
+ XCTAssertEqual(2ULL, GPBEncodeZigZag64(1));
+ XCTAssertEqual(3ULL, GPBEncodeZigZag64(-2));
+ XCTAssertEqual(0x000000007FFFFFFEULL,
+ GPBEncodeZigZag64(0x000000003FFFFFFFLL));
+ XCTAssertEqual(0x000000007FFFFFFFULL,
+ GPBEncodeZigZag64(0xFFFFFFFFC0000000LL));
+ XCTAssertEqual(0x00000000FFFFFFFEULL,
+ GPBEncodeZigZag64(0x000000007FFFFFFFLL));
+ XCTAssertEqual(0x00000000FFFFFFFFULL,
+ GPBEncodeZigZag64(0xFFFFFFFF80000000LL));
+ XCTAssertEqual(0xFFFFFFFFFFFFFFFEULL,
+ GPBEncodeZigZag64(0x7FFFFFFFFFFFFFFFLL));
+ XCTAssertEqual(0xFFFFFFFFFFFFFFFFULL,
+ GPBEncodeZigZag64(0x8000000000000000LL));
+
+ // Some easier-to-verify round-trip tests. The inputs (other than 0, 1, -1)
+ // were chosen semi-randomly via keyboard bashing.
+ XCTAssertEqual(0U, GPBEncodeZigZag32(GPBDecodeZigZag32(0)));
+ XCTAssertEqual(1U, GPBEncodeZigZag32(GPBDecodeZigZag32(1)));
+ XCTAssertEqual(-1U, GPBEncodeZigZag32(GPBDecodeZigZag32(-1)));
+ XCTAssertEqual(14927U, GPBEncodeZigZag32(GPBDecodeZigZag32(14927)));
+ XCTAssertEqual(-3612U, GPBEncodeZigZag32(GPBDecodeZigZag32(-3612)));
+
+ XCTAssertEqual(0ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(0)));
+ XCTAssertEqual(1ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(1)));
+ XCTAssertEqual(-1ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-1)));
+ XCTAssertEqual(14927ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(14927)));
+ XCTAssertEqual(-3612ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-3612)));
+
+ XCTAssertEqual(856912304801416ULL,
+ GPBEncodeZigZag64(GPBDecodeZigZag64(856912304801416LL)));
+ XCTAssertEqual(-75123905439571256ULL,
+ GPBEncodeZigZag64(GPBDecodeZigZag64(-75123905439571256LL)));
+}
+
+- (void)testWriteWholeMessage {
+ // Not kGPBDefaultRepeatCount because we are comparing to a golden master file
+ // that was generated with 2.
+ TestAllTypes* message = [self allSetRepeatedCount:2];
+
+ NSData* rawBytes = message.data;
+ NSData* goldenData =
+ [self getDataFileNamed:@"golden_message" dataToWrite:rawBytes];
+ XCTAssertEqualObjects(rawBytes, goldenData);
+
+ // Try different block sizes.
+ for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
+ NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
+ GPBCodedOutputStream* output =
+ [GPBCodedOutputStream streamWithOutputStream:rawOutput
+ bufferSize:blockSize];
+ [message writeToCodedOutputStream:output];
+ [output flush];
+
+ NSData* actual =
+ [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+ XCTAssertEqualObjects(rawBytes, actual);
+ }
+
+ // Not kGPBDefaultRepeatCount because we are comparing to a golden master file
+ // that was generated with 2.
+ TestAllExtensions* extensions = [self allExtensionsSetRepeatedCount:2];
+ rawBytes = extensions.data;
+ goldenData = [self getDataFileNamed:@"golden_packed_fields_message"
+ dataToWrite:rawBytes];
+ XCTAssertEqualObjects(rawBytes, goldenData);
+}
+
+@end
diff --git a/objectivec/Tests/GPBConcurrencyTests.m b/objectivec/Tests/GPBConcurrencyTests.m
new file mode 100644
index 00000000..3749fc34
--- /dev/null
+++ b/objectivec/Tests/GPBConcurrencyTests.m
@@ -0,0 +1,157 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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 "GPBTestUtilities.h"
+
+#import "google/protobuf/Unittest.pbobjc.h"
+
+static const int kNumThreads = 100;
+static const int kNumMessages = 100;
+
+@interface ConcurrencyTests : GPBTestCase
+@end
+
+@implementation ConcurrencyTests
+
+- (NSArray *)createThreadsWithSelector:(SEL)selector object:(id)object {
+ NSMutableArray *array = [NSMutableArray array];
+ for (NSUInteger i = 0; i < kNumThreads; i++) {
+ NSThread *thread =
+ [[NSThread alloc] initWithTarget:self selector:selector object:object];
+ [array addObject:thread];
+ [thread release];
+ }
+ return array;
+}
+
+- (NSArray *)createMessagesWithType:(Class)msgType {
+ NSMutableArray *array = [NSMutableArray array];
+ for (NSUInteger i = 0; i < kNumMessages; i++) {
+ [array addObject:[msgType message]];
+ }
+ return array;
+}
+
+- (void)startThreads:(NSArray *)threads {
+ for (NSThread *thread in threads) {
+ [thread start];
+ }
+}
+
+- (void)joinThreads:(NSArray *)threads {
+ for (NSThread *thread in threads) {
+ while (![thread isFinished])
+ ;
+ }
+}
+
+- (void)readForeignMessage:(NSArray *)messages {
+ for (NSUInteger i = 0; i < 10; i++) {
+ for (TestAllTypes *message in messages) {
+ XCTAssertEqual(message.optionalForeignMessage.c, 0);
+ }
+ }
+}
+
+- (void)testConcurrentReadOfUnsetMessageField {
+ NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
+ NSArray *threads =
+ [self createThreadsWithSelector:@selector(readForeignMessage:)
+ object:messages];
+ [self startThreads:threads];
+ [self joinThreads:threads];
+ for (TestAllTypes *message in messages) {
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ }
+}
+
+- (void)readRepeatedInt32:(NSArray *)messages {
+ for (int i = 0; i < 10; i++) {
+ for (TestAllTypes *message in messages) {
+ XCTAssertEqual([message.repeatedInt32Array count], (NSUInteger)0);
+ }
+ }
+}
+
+- (void)testConcurrentReadOfUnsetRepeatedIntField {
+ NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
+ NSArray *threads =
+ [self createThreadsWithSelector:@selector(readRepeatedInt32:)
+ object:messages];
+ [self startThreads:threads];
+ [self joinThreads:threads];
+ for (TestAllTypes *message in messages) {
+ XCTAssertEqual([message.repeatedInt32Array count], (NSUInteger)0);
+ }
+}
+
+- (void)readRepeatedString:(NSArray *)messages {
+ for (int i = 0; i < 10; i++) {
+ for (TestAllTypes *message in messages) {
+ XCTAssertEqual([message.repeatedStringArray count], (NSUInteger)0);
+ }
+ }
+}
+
+- (void)testConcurrentReadOfUnsetRepeatedStringField {
+ NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
+ NSArray *threads =
+ [self createThreadsWithSelector:@selector(readRepeatedString:)
+ object:messages];
+ [self startThreads:threads];
+ [self joinThreads:threads];
+ for (TestAllTypes *message in messages) {
+ XCTAssertEqual([message.repeatedStringArray count], (NSUInteger)0);
+ }
+}
+
+- (void)readOptionalForeignMessageExtension:(NSArray *)messages {
+ for (int i = 0; i < 10; i++) {
+ for (TestAllExtensions *message in messages) {
+ ForeignMessage *foreign =
+ [message getExtension:[UnittestRoot optionalForeignMessageExtension]];
+ XCTAssertEqual(foreign.c, 0);
+ }
+ }
+}
+
+- (void)testConcurrentReadOfUnsetExtensionField {
+ NSArray *messages = [self createMessagesWithType:[TestAllExtensions class]];
+ SEL sel = @selector(readOptionalForeignMessageExtension:);
+ NSArray *threads = [self createThreadsWithSelector:sel object:messages];
+ [self startThreads:threads];
+ [self joinThreads:threads];
+ GPBExtensionField *extension = [UnittestRoot optionalForeignMessageExtension];
+ for (TestAllExtensions *message in messages) {
+ XCTAssertFalse([message hasExtension:extension]);
+ }
+}
+
+@end
diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m
new file mode 100644
index 00000000..ccdbb645
--- /dev/null
+++ b/objectivec/Tests/GPBDescriptorTests.m
@@ -0,0 +1,232 @@
+// 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 "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBDescriptor.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface DescriptorTests : GPBTestCase
+@end
+
+@implementation DescriptorTests
+
+- (void)testFieldDescriptor {
+ GPBDescriptor *descriptor = [TestAllTypes descriptor];
+
+ // Nested Enum
+ GPBFieldDescriptor *fieldDescriptorWithName =
+ [descriptor fieldWithName:@"optionalNestedEnum"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ GPBFieldDescriptor *fieldDescriptorWithNumber =
+ [descriptor fieldWithNumber:21];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
+ XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
+ @"TestAllTypes_NestedEnum");
+
+ // Foreign Enum
+ fieldDescriptorWithName = [descriptor fieldWithName:@"optionalForeignEnum"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ fieldDescriptorWithNumber = [descriptor fieldWithNumber:22];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
+ XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
+ @"ForeignEnum");
+
+ // Import Enum
+ fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportEnum"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ fieldDescriptorWithNumber = [descriptor fieldWithNumber:23];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
+ XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
+ @"ImportEnum");
+
+ // Nested Message
+ fieldDescriptorWithName = [descriptor fieldWithName:@"optionalNestedMessage"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ fieldDescriptorWithNumber = [descriptor fieldWithNumber:18];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
+
+ // Foreign Message
+ fieldDescriptorWithName =
+ [descriptor fieldWithName:@"optionalForeignMessage"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ fieldDescriptorWithNumber = [descriptor fieldWithNumber:19];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
+
+ // Import Message
+ fieldDescriptorWithName = [descriptor fieldWithName:@"optionalImportMessage"];
+ XCTAssertNotNil(fieldDescriptorWithName);
+ fieldDescriptorWithNumber = [descriptor fieldWithNumber:20];
+ XCTAssertNotNil(fieldDescriptorWithNumber);
+ XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
+ XCTAssertNil(fieldDescriptorWithNumber.enumDescriptor);
+}
+
+- (void)testEnumDescriptor {
+ GPBEnumDescriptor *descriptor = TestAllTypes_NestedEnum_EnumDescriptor();
+
+ NSString *enumName = [descriptor enumNameForValue:1];
+ XCTAssertNotNil(enumName);
+ int32_t value;
+ XCTAssertTrue(
+ [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
+ XCTAssertTrue(
+ [descriptor getValue:NULL forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
+ XCTAssertEqual(value, TestAllTypes_NestedEnum_Foo);
+
+ enumName = [descriptor enumNameForValue:2];
+ XCTAssertNotNil(enumName);
+ XCTAssertTrue(
+ [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Bar"]);
+ XCTAssertEqual(value, TestAllTypes_NestedEnum_Bar);
+
+ enumName = [descriptor enumNameForValue:3];
+ XCTAssertNotNil(enumName);
+ XCTAssertTrue(
+ [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Baz"]);
+ XCTAssertEqual(value, TestAllTypes_NestedEnum_Baz);
+
+ // Bad values
+ enumName = [descriptor enumNameForValue:0];
+ XCTAssertNil(enumName);
+ XCTAssertFalse([descriptor getValue:&value forEnumName:@"Unknown"]);
+ XCTAssertFalse([descriptor getValue:NULL forEnumName:@"Unknown"]);
+ XCTAssertFalse([descriptor getValue:&value
+ forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
+ XCTAssertFalse([descriptor getValue:NULL
+ forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
+}
+
+- (void)testEnumValueValidator {
+ GPBDescriptor *descriptor = [TestAllTypes descriptor];
+ GPBFieldDescriptor *fieldDescriptor =
+ [descriptor fieldWithName:@"optionalNestedEnum"];
+
+ // Valid values
+ XCTAssertTrue([fieldDescriptor isValidEnumValue:1]);
+ XCTAssertTrue([fieldDescriptor isValidEnumValue:2]);
+ XCTAssertTrue([fieldDescriptor isValidEnumValue:3]);
+ XCTAssertTrue([fieldDescriptor isValidEnumValue:-1]);
+
+ // Invalid values
+ XCTAssertFalse([fieldDescriptor isValidEnumValue:4]);
+ XCTAssertFalse([fieldDescriptor isValidEnumValue:0]);
+ XCTAssertFalse([fieldDescriptor isValidEnumValue:-2]);
+}
+
+- (void)testEnumDescriptorLookup {
+ GPBDescriptor *descriptor = [TestAllTypes descriptor];
+ GPBEnumDescriptor *enumDescriptor =
+ [descriptor enumWithName:@"TestAllTypes_NestedEnum"];
+ XCTAssertNotNil(enumDescriptor);
+
+ // Descriptor cannot find foreign or imported enums.
+ enumDescriptor = [descriptor enumWithName:@"ForeignEnumEnum"];
+ XCTAssertNil(enumDescriptor);
+ enumDescriptor = [descriptor enumWithName:@"ImportEnumEnum"];
+ XCTAssertNil(enumDescriptor);
+}
+
+- (void)testOneofDescriptor {
+ GPBDescriptor *descriptor = [TestOneof2 descriptor];
+
+ // All fields should be listed.
+ XCTAssertEqual(descriptor.fields.count, 17U);
+
+ // There are two oneofs in there.
+ XCTAssertEqual(descriptor.oneofs.count, 2U);
+
+ GPBFieldDescriptor *fooStringField =
+ [descriptor fieldWithNumber:TestOneof2_FieldNumber_FooString];
+ XCTAssertNotNil(fooStringField);
+ GPBFieldDescriptor *barStringField =
+ [descriptor fieldWithNumber:TestOneof2_FieldNumber_BarString];
+ XCTAssertNotNil(barStringField);
+
+ // Check the oneofs to have what is expected.
+
+ GPBOneofDescriptor *oneofFoo = [descriptor oneofWithName:@"foo"];
+ XCTAssertNotNil(oneofFoo);
+ XCTAssertEqual(oneofFoo.fields.count, 9U);
+
+ // Pointer comparisons.
+ XCTAssertEqual([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_FooString],
+ fooStringField);
+ XCTAssertEqual([oneofFoo fieldWithName:@"fooString"], fooStringField);
+
+ GPBOneofDescriptor *oneofBar = [descriptor oneofWithName:@"bar"];
+ XCTAssertNotNil(oneofBar);
+ XCTAssertEqual(oneofBar.fields.count, 6U);
+
+ // Pointer comparisons.
+ XCTAssertEqual([oneofBar fieldWithNumber:TestOneof2_FieldNumber_BarString],
+ barStringField);
+ XCTAssertEqual([oneofBar fieldWithName:@"barString"], barStringField);
+
+ // Unknown oneof not found.
+
+ XCTAssertNil([descriptor oneofWithName:@"mumble"]);
+ XCTAssertNil([descriptor oneofWithName:@"Foo"]);
+
+ // Unknown oneof item.
+
+ XCTAssertNil([oneofFoo fieldWithName:@"mumble"]);
+ XCTAssertNil([oneofFoo fieldWithNumber:666]);
+
+ // Field exists, but not in this oneof.
+
+ XCTAssertNil([oneofFoo fieldWithName:@"barString"]);
+ XCTAssertNil([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_BarString]);
+ XCTAssertNil([oneofBar fieldWithName:@"fooString"]);
+ XCTAssertNil([oneofBar fieldWithNumber:TestOneof2_FieldNumber_FooString]);
+
+ // Check pointers back to the enclosing oneofs.
+ // (pointer comparisions)
+ XCTAssertEqual(fooStringField.containingOneof, oneofFoo);
+ XCTAssertEqual(barStringField.containingOneof, oneofBar);
+ GPBFieldDescriptor *bazString =
+ [descriptor fieldWithNumber:TestOneof2_FieldNumber_BazString];
+ XCTAssertNotNil(bazString);
+ XCTAssertNil(bazString.containingOneof);
+}
+
+@end
diff --git a/objectivec/Tests/GPBDictionaryTests+Bool.m b/objectivec/Tests/GPBDictionaryTests+Bool.m
new file mode 100644
index 00000000..bc4998be
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+Bool.m
@@ -0,0 +1,2421 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(UInt32, uint32_t, 100U, 101U)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> UInt32
+
+@interface GPBBoolUInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolUInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBBoolUInt32Dictionary *dict = [[GPBBoolUInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolUInt32Dictionary *dict = [GPBBoolUInt32Dictionary dictionaryWithValue:100U forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const uint32_t kValues[] = { 100U, 101U };
+ GPBBoolUInt32Dictionary *dict =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ uint32_t *seenValues = malloc(2 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const uint32_t kValues1[] = { 100U, 101U };
+ const uint32_t kValues2[] = { 101U, 100U };
+ const uint32_t kValues3[] = { 101U };
+ GPBBoolUInt32Dictionary *dict1 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolUInt32Dictionary *dict1prime =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolUInt32Dictionary *dict2 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolUInt32Dictionary *dict3 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolUInt32Dictionary *dict4 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const uint32_t kValues[] = { 100U, 101U };
+ GPBBoolUInt32Dictionary *dict =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolUInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolUInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const uint32_t kValues[] = { 100U, 101U };
+ GPBBoolUInt32Dictionary *dict =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolUInt32Dictionary *dict2 =
+ [GPBBoolUInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolUInt32Dictionary *dict = [GPBBoolUInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const uint32_t kValues[] = { 101U };
+ GPBBoolUInt32Dictionary *dict2 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 101U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const uint32_t kValues[] = { 100U, 101U };
+ GPBBoolUInt32Dictionary *dict =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const uint32_t kValues[] = { 100U, 101U };
+ GPBBoolUInt32Dictionary *dict =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict setValue:101U forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict setValue:100U forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 100U);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const uint32_t kValues2[] = { 101U, 100U };
+ GPBBoolUInt32Dictionary *dict2 =
+ [[GPBBoolUInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Int32, int32_t, 200, 201)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Int32
+
+@interface GPBBoolInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBBoolInt32Dictionary *dict = [[GPBBoolInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolInt32Dictionary *dict = [GPBBoolInt32Dictionary dictionaryWithValue:200 forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const int32_t kValues[] = { 200, 201 };
+ GPBBoolInt32Dictionary *dict =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 201);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ int32_t *seenValues = malloc(2 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const int32_t kValues1[] = { 200, 201 };
+ const int32_t kValues2[] = { 201, 200 };
+ const int32_t kValues3[] = { 201 };
+ GPBBoolInt32Dictionary *dict1 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolInt32Dictionary *dict1prime =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolInt32Dictionary *dict2 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolInt32Dictionary *dict3 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolInt32Dictionary *dict4 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const int32_t kValues[] = { 200, 201 };
+ GPBBoolInt32Dictionary *dict =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const int32_t kValues[] = { 200, 201 };
+ GPBBoolInt32Dictionary *dict =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolInt32Dictionary *dict2 =
+ [GPBBoolInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolInt32Dictionary *dict = [GPBBoolInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const int32_t kValues[] = { 201 };
+ GPBBoolInt32Dictionary *dict2 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 201);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const int32_t kValues[] = { 200, 201 };
+ GPBBoolInt32Dictionary *dict =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const int32_t kValues[] = { 200, 201 };
+ GPBBoolInt32Dictionary *dict =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict setValue:201 forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict setValue:200 forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 200);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const int32_t kValues2[] = { 201, 200 };
+ GPBBoolInt32Dictionary *dict2 =
+ [[GPBBoolInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(UInt64, uint64_t, 300U, 301U)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> UInt64
+
+@interface GPBBoolUInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolUInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBBoolUInt64Dictionary *dict = [[GPBBoolUInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolUInt64Dictionary *dict = [GPBBoolUInt64Dictionary dictionaryWithValue:300U forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const uint64_t kValues[] = { 300U, 301U };
+ GPBBoolUInt64Dictionary *dict =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ uint64_t *seenValues = malloc(2 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const uint64_t kValues1[] = { 300U, 301U };
+ const uint64_t kValues2[] = { 301U, 300U };
+ const uint64_t kValues3[] = { 301U };
+ GPBBoolUInt64Dictionary *dict1 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolUInt64Dictionary *dict1prime =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolUInt64Dictionary *dict2 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolUInt64Dictionary *dict3 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolUInt64Dictionary *dict4 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const uint64_t kValues[] = { 300U, 301U };
+ GPBBoolUInt64Dictionary *dict =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolUInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolUInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const uint64_t kValues[] = { 300U, 301U };
+ GPBBoolUInt64Dictionary *dict =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolUInt64Dictionary *dict2 =
+ [GPBBoolUInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolUInt64Dictionary *dict = [GPBBoolUInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const uint64_t kValues[] = { 301U };
+ GPBBoolUInt64Dictionary *dict2 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 301U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const uint64_t kValues[] = { 300U, 301U };
+ GPBBoolUInt64Dictionary *dict =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const uint64_t kValues[] = { 300U, 301U };
+ GPBBoolUInt64Dictionary *dict =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict setValue:301U forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict setValue:300U forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 300U);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const uint64_t kValues2[] = { 301U, 300U };
+ GPBBoolUInt64Dictionary *dict2 =
+ [[GPBBoolUInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Int64, int64_t, 400, 401)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Int64
+
+@interface GPBBoolInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBBoolInt64Dictionary *dict = [[GPBBoolInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolInt64Dictionary *dict = [GPBBoolInt64Dictionary dictionaryWithValue:400 forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const int64_t kValues[] = { 400, 401 };
+ GPBBoolInt64Dictionary *dict =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 401);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ int64_t *seenValues = malloc(2 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const int64_t kValues1[] = { 400, 401 };
+ const int64_t kValues2[] = { 401, 400 };
+ const int64_t kValues3[] = { 401 };
+ GPBBoolInt64Dictionary *dict1 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolInt64Dictionary *dict1prime =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolInt64Dictionary *dict2 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolInt64Dictionary *dict3 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolInt64Dictionary *dict4 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const int64_t kValues[] = { 400, 401 };
+ GPBBoolInt64Dictionary *dict =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const int64_t kValues[] = { 400, 401 };
+ GPBBoolInt64Dictionary *dict =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolInt64Dictionary *dict2 =
+ [GPBBoolInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolInt64Dictionary *dict = [GPBBoolInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const int64_t kValues[] = { 401 };
+ GPBBoolInt64Dictionary *dict2 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 401);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const int64_t kValues[] = { 400, 401 };
+ GPBBoolInt64Dictionary *dict =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const int64_t kValues[] = { 400, 401 };
+ GPBBoolInt64Dictionary *dict =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict setValue:401 forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict setValue:400 forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 400);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const int64_t kValues2[] = { 401, 400 };
+ GPBBoolInt64Dictionary *dict2 =
+ [[GPBBoolInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Bool, BOOL, NO, YES)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Bool
+
+@interface GPBBoolBoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolBoolDictionaryTests
+
+- (void)testEmpty {
+ GPBBoolBoolDictionary *dict = [[GPBBoolBoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolBoolDictionary *dict = [GPBBoolBoolDictionary dictionaryWithValue:NO forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, NO);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const BOOL kValues[] = { NO, YES };
+ GPBBoolBoolDictionary *dict =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, YES);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ BOOL *seenValues = malloc(2 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const BOOL kValues1[] = { NO, YES };
+ const BOOL kValues2[] = { YES, NO };
+ const BOOL kValues3[] = { YES };
+ GPBBoolBoolDictionary *dict1 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolBoolDictionary *dict1prime =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolBoolDictionary *dict2 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolBoolDictionary *dict3 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolBoolDictionary *dict4 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const BOOL kValues[] = { NO, YES };
+ GPBBoolBoolDictionary *dict =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolBoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolBoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const BOOL kValues[] = { NO, YES };
+ GPBBoolBoolDictionary *dict =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolBoolDictionary *dict2 =
+ [GPBBoolBoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolBoolDictionary *dict = [GPBBoolBoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:NO forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const BOOL kValues[] = { YES };
+ GPBBoolBoolDictionary *dict2 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, YES);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const BOOL kValues[] = { NO, YES };
+ GPBBoolBoolDictionary *dict =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const BOOL kValues[] = { NO, YES };
+ GPBBoolBoolDictionary *dict =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict setValue:YES forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict setValue:NO forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, NO);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const BOOL kValues2[] = { YES, NO };
+ GPBBoolBoolDictionary *dict2 =
+ [[GPBBoolBoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Float, float, 500.f, 501.f)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Float
+
+@interface GPBBoolFloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolFloatDictionaryTests
+
+- (void)testEmpty {
+ GPBBoolFloatDictionary *dict = [[GPBBoolFloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolFloatDictionary *dict = [GPBBoolFloatDictionary dictionaryWithValue:500.f forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const float kValues[] = { 500.f, 501.f };
+ GPBBoolFloatDictionary *dict =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ float value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ float *seenValues = malloc(2 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const float kValues1[] = { 500.f, 501.f };
+ const float kValues2[] = { 501.f, 500.f };
+ const float kValues3[] = { 501.f };
+ GPBBoolFloatDictionary *dict1 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolFloatDictionary *dict1prime =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolFloatDictionary *dict2 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolFloatDictionary *dict3 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolFloatDictionary *dict4 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const float kValues[] = { 500.f, 501.f };
+ GPBBoolFloatDictionary *dict =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolFloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolFloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const float kValues[] = { 500.f, 501.f };
+ GPBBoolFloatDictionary *dict =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolFloatDictionary *dict2 =
+ [GPBBoolFloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolFloatDictionary *dict = [GPBBoolFloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const float kValues[] = { 501.f };
+ GPBBoolFloatDictionary *dict2 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 501.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const float kValues[] = { 500.f, 501.f };
+ GPBBoolFloatDictionary *dict =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const float kValues[] = { 500.f, 501.f };
+ GPBBoolFloatDictionary *dict =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ float value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict setValue:501.f forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict setValue:500.f forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 500.f);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const float kValues2[] = { 501.f, 500.f };
+ GPBBoolFloatDictionary *dict2 =
+ [[GPBBoolFloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Double, double, 600., 601.)
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Double
+
+@interface GPBBoolDoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolDoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBBoolDoubleDictionary *dict = [[GPBBoolDoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolDoubleDictionary *dict = [GPBBoolDoubleDictionary dictionaryWithValue:600. forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const double kValues[] = { 600., 601. };
+ GPBBoolDoubleDictionary *dict =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ double value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ double *seenValues = malloc(2 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const double kValues1[] = { 600., 601. };
+ const double kValues2[] = { 601., 600. };
+ const double kValues3[] = { 601. };
+ GPBBoolDoubleDictionary *dict1 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolDoubleDictionary *dict1prime =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolDoubleDictionary *dict2 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolDoubleDictionary *dict3 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolDoubleDictionary *dict4 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const double kValues[] = { 600., 601. };
+ GPBBoolDoubleDictionary *dict =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolDoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolDoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const double kValues[] = { 600., 601. };
+ GPBBoolDoubleDictionary *dict =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolDoubleDictionary *dict2 =
+ [GPBBoolDoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolDoubleDictionary *dict = [GPBBoolDoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const double kValues[] = { 601. };
+ GPBBoolDoubleDictionary *dict2 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 601.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const double kValues[] = { 600., 601. };
+ GPBBoolDoubleDictionary *dict =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:YES value:NULL]);
+ XCTAssertFalse([dict valueForKey:NO value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const double kValues[] = { 600., 601. };
+ GPBBoolDoubleDictionary *dict =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ double value;
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict setValue:601. forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict setValue:600. forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 600.);
+
+ const BOOL kKeys2[] = { NO, YES };
+ const double kValues2[] = { 601., 600. };
+ GPBBoolDoubleDictionary *dict2 =
+ [[GPBBoolDoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:YES value:NULL]);
+ XCTAssertTrue([dict valueForKey:YES value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:NO value:NULL]);
+ XCTAssertTrue([dict valueForKey:NO value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND TESTS_FOR_BOOL_KEY_OBJECT_VALUE(Object, id, @"abc", @"def")
+// This block of code is generated, do not edit it directly.
+
+#pragma mark - Bool -> Object
+
+@interface GPBBoolObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBBoolObjectDictionaryTests
+
+- (void)testEmpty {
+ GPBBoolObjectDictionary *dict = [[GPBBoolObjectDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:YES]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBBoolObjectDictionary *dict = [GPBBoolObjectDictionary dictionaryWithValue:@"abc" forKey:YES];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertNil([dict valueForKey:NO]);
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, id aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, YES);
+ XCTAssertEqualObjects(aValue, @"abc");
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const BOOL kKeys[] = { YES, NO };
+ const id kValues[] = { @"abc", @"def" };
+ GPBBoolObjectDictionary *dict =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"def");
+
+ __block NSUInteger idx = 0;
+ BOOL *seenKeys = malloc(2 * sizeof(BOOL));
+ id *seenValues = malloc(2 * sizeof(id));
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, id aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 2U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 2; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 2) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqualObjects(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(BOOL aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 0) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const BOOL kKeys1[] = { YES, NO };
+ const BOOL kKeys2[] = { NO, YES };
+ const id kValues1[] = { @"abc", @"def" };
+ const id kValues2[] = { @"def", @"abc" };
+ const id kValues3[] = { @"def" };
+ GPBBoolObjectDictionary *dict1 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBBoolObjectDictionary *dict1prime =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBBoolObjectDictionary *dict2 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBBoolObjectDictionary *dict3 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBBoolObjectDictionary *dict4 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 Fewer pairs; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const BOOL kKeys[] = { YES, NO };
+ const id kValues[] = { @"abc", @"def" };
+ GPBBoolObjectDictionary *dict =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolObjectDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBBoolObjectDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const BOOL kKeys[] = { YES, NO };
+ const id kValues[] = { @"abc", @"def" };
+ GPBBoolObjectDictionary *dict =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBBoolObjectDictionary *dict2 =
+ [GPBBoolObjectDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBBoolObjectDictionary *dict = [GPBBoolObjectDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:@"abc" forKey:YES];
+ XCTAssertEqual(dict.count, 1U);
+
+ const BOOL kKeys[] = { NO };
+ const id kValues[] = { @"def" };
+ GPBBoolObjectDictionary *dict2 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"def");
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const BOOL kKeys[] = { YES, NO};
+ const id kValues[] = { @"abc", @"def" };
+ GPBBoolObjectDictionary *dict =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertNil([dict valueForKey:NO]);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:NO];
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertNil([dict valueForKey:NO]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:YES]);
+ XCTAssertNil([dict valueForKey:NO]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const BOOL kKeys[] = { YES, NO };
+ const id kValues[] = { @"abc", @"def" };
+ GPBBoolObjectDictionary *dict =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"def");
+
+ [dict setValue:@"def" forKey:YES];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"def");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"def");
+
+ [dict setValue:@"abc" forKey:NO];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"def");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"abc");
+
+ const BOOL kKeys2[] = { NO, YES };
+ const id kValues2[] = { @"def", @"abc" };
+ GPBBoolObjectDictionary *dict2 =
+ [[GPBBoolObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:YES], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:NO], @"def");
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END (8 expansions)
+
+
diff --git a/objectivec/Tests/GPBDictionaryTests+Int32.m b/objectivec/Tests/GPBDictionaryTests+Int32.m
new file mode 100644
index 00000000..5e25799c
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+Int32.m
@@ -0,0 +1,3650 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14)
+// This block of code is generated, do not edit it directly.
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int32_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 700:
+ case 701:
+ case 702:
+ case 703:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int32_t)key {
+ // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+ // type correct.
+ return [[(GPBInt32EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int32_t [])keys
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ forKeys:keys
+ count:count];
+}
+@end
+
+
+#pragma mark - Int32 -> UInt32
+
+@interface GPBInt32UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32UInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBInt32UInt32Dictionary *dict = [[GPBInt32UInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32UInt32Dictionary *dict = [GPBInt32UInt32Dictionary dictionaryWithValue:100U forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const uint32_t kValues[] = { 100U, 101U, 102U };
+ GPBInt32UInt32Dictionary *dict =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const uint32_t kValues1[] = { 100U, 101U, 102U };
+ const uint32_t kValues2[] = { 100U, 103U, 102U };
+ const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict1 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32UInt32Dictionary *dict1prime =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32UInt32Dictionary *dict2 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32UInt32Dictionary *dict3 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32UInt32Dictionary *dict4 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32UInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32UInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32UInt32Dictionary *dict2 =
+ [GPBInt32UInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32UInt32Dictionary *dict = [GPBInt32UInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const uint32_t kValues[] = { 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict2 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 103U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt32UInt32Dictionary *dict =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:103U forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:101U forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const uint32_t kValues2[] = { 102U, 100U };
+ GPBInt32UInt32Dictionary *dict2 =
+ [[GPBInt32UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Int32
+
+@interface GPBInt32Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32Int32DictionaryTests
+
+- (void)testEmpty {
+ GPBInt32Int32Dictionary *dict = [[GPBInt32Int32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32Int32Dictionary *dict = [GPBInt32Int32Dictionary dictionaryWithValue:200 forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const int32_t kValues[] = { 200, 201, 202 };
+ GPBInt32Int32Dictionary *dict =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const int32_t kValues1[] = { 200, 201, 202 };
+ const int32_t kValues2[] = { 200, 203, 202 };
+ const int32_t kValues3[] = { 200, 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict1 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32Int32Dictionary *dict1prime =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32Int32Dictionary *dict2 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32Int32Dictionary *dict3 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32Int32Dictionary *dict4 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32Int32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32Int32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32Int32Dictionary *dict2 =
+ [GPBInt32Int32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32Int32Dictionary *dict = [GPBInt32Int32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const int32_t kValues[] = { 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict2 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 203);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 203);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt32Int32Dictionary *dict =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:203 forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:201 forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 201);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const int32_t kValues2[] = { 202, 200 };
+ GPBInt32Int32Dictionary *dict2 =
+ [[GPBInt32Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> UInt64
+
+@interface GPBInt32UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32UInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBInt32UInt64Dictionary *dict = [[GPBInt32UInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32UInt64Dictionary *dict = [GPBInt32UInt64Dictionary dictionaryWithValue:300U forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const uint64_t kValues[] = { 300U, 301U, 302U };
+ GPBInt32UInt64Dictionary *dict =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const uint64_t kValues1[] = { 300U, 301U, 302U };
+ const uint64_t kValues2[] = { 300U, 303U, 302U };
+ const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict1 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32UInt64Dictionary *dict1prime =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32UInt64Dictionary *dict2 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32UInt64Dictionary *dict3 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32UInt64Dictionary *dict4 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32UInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32UInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32UInt64Dictionary *dict2 =
+ [GPBInt32UInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32UInt64Dictionary *dict = [GPBInt32UInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const uint64_t kValues[] = { 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict2 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 303U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt32UInt64Dictionary *dict =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:303U forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:301U forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const uint64_t kValues2[] = { 302U, 300U };
+ GPBInt32UInt64Dictionary *dict2 =
+ [[GPBInt32UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Int64
+
+@interface GPBInt32Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32Int64DictionaryTests
+
+- (void)testEmpty {
+ GPBInt32Int64Dictionary *dict = [[GPBInt32Int64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32Int64Dictionary *dict = [GPBInt32Int64Dictionary dictionaryWithValue:400 forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const int64_t kValues[] = { 400, 401, 402 };
+ GPBInt32Int64Dictionary *dict =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ int64_t *seenValues = malloc(3 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const int64_t kValues1[] = { 400, 401, 402 };
+ const int64_t kValues2[] = { 400, 403, 402 };
+ const int64_t kValues3[] = { 400, 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict1 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32Int64Dictionary *dict1prime =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32Int64Dictionary *dict2 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32Int64Dictionary *dict3 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32Int64Dictionary *dict4 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32Int64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32Int64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32Int64Dictionary *dict2 =
+ [GPBInt32Int64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32Int64Dictionary *dict = [GPBInt32Int64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const int64_t kValues[] = { 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict2 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 403);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 403);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt32Int64Dictionary *dict =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:403 forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:401 forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 401);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const int64_t kValues2[] = { 402, 400 };
+ GPBInt32Int64Dictionary *dict2 =
+ [[GPBInt32Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Bool
+
+@interface GPBInt32BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32BoolDictionaryTests
+
+- (void)testEmpty {
+ GPBInt32BoolDictionary *dict = [[GPBInt32BoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32BoolDictionary *dict = [GPBInt32BoolDictionary dictionaryWithValue:YES forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, YES);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const BOOL kValues[] = { YES, YES, NO };
+ GPBInt32BoolDictionary *dict =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ BOOL *seenValues = malloc(3 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const BOOL kValues1[] = { YES, YES, NO };
+ const BOOL kValues2[] = { YES, NO, NO };
+ const BOOL kValues3[] = { YES, YES, NO, NO };
+ GPBInt32BoolDictionary *dict1 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32BoolDictionary *dict1prime =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32BoolDictionary *dict2 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32BoolDictionary *dict3 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32BoolDictionary *dict4 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt32BoolDictionary *dict =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32BoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32BoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt32BoolDictionary *dict =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32BoolDictionary *dict2 =
+ [GPBInt32BoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32BoolDictionary *dict = [GPBInt32BoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:YES forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const BOOL kValues[] = { YES, NO, NO };
+ GPBInt32BoolDictionary *dict2 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, NO);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt32BoolDictionary *dict =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, NO);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt32BoolDictionary *dict =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:NO forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:YES forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, YES);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const BOOL kValues2[] = { NO, YES };
+ GPBInt32BoolDictionary *dict2 =
+ [[GPBInt32BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Float
+
+@interface GPBInt32FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32FloatDictionaryTests
+
+- (void)testEmpty {
+ GPBInt32FloatDictionary *dict = [[GPBInt32FloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32FloatDictionary *dict = [GPBInt32FloatDictionary dictionaryWithValue:500.f forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const float kValues[] = { 500.f, 501.f, 502.f };
+ GPBInt32FloatDictionary *dict =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ float *seenValues = malloc(3 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const float kValues1[] = { 500.f, 501.f, 502.f };
+ const float kValues2[] = { 500.f, 503.f, 502.f };
+ const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict1 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32FloatDictionary *dict1prime =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32FloatDictionary *dict2 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32FloatDictionary *dict3 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32FloatDictionary *dict4 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32FloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32FloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32FloatDictionary *dict2 =
+ [GPBInt32FloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32FloatDictionary *dict = [GPBInt32FloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const float kValues[] = { 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict2 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 503.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt32FloatDictionary *dict =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ float value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:503.f forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:501.f forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const float kValues2[] = { 502.f, 500.f };
+ GPBInt32FloatDictionary *dict2 =
+ [[GPBInt32FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Double
+
+@interface GPBInt32DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32DoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBInt32DoubleDictionary *dict = [[GPBInt32DoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32DoubleDictionary *dict = [GPBInt32DoubleDictionary dictionaryWithValue:600. forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const double kValues[] = { 600., 601., 602. };
+ GPBInt32DoubleDictionary *dict =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ double *seenValues = malloc(3 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const double kValues1[] = { 600., 601., 602. };
+ const double kValues2[] = { 600., 603., 602. };
+ const double kValues3[] = { 600., 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict1 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32DoubleDictionary *dict1prime =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32DoubleDictionary *dict2 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32DoubleDictionary *dict3 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32DoubleDictionary *dict4 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32DoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32DoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32DoubleDictionary *dict2 =
+ [GPBInt32DoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32DoubleDictionary *dict = [GPBInt32DoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const double kValues[] = { 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict2 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 603.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt32DoubleDictionary *dict =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ double value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:603. forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:601. forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const double kValues2[] = { 602., 600. };
+ GPBInt32DoubleDictionary *dict2 =
+ [[GPBInt32DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Enum
+
+@interface GPBInt32EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32EnumDictionaryTests
+
+- (void)testEmpty {
+ GPBInt32EnumDictionary *dict = [[GPBInt32EnumDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32EnumDictionary *dict = [GPBInt32EnumDictionary dictionaryWithValue:700 forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqual(aValue, 700);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const int32_t kValues[] = { 700, 701, 702 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const int32_t kValues1[] = { 700, 701, 702 };
+ const int32_t kValues2[] = { 700, 703, 702 };
+ const int32_t kValues3[] = { 700, 701, 702, 703 };
+ GPBInt32EnumDictionary *dict1 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32EnumDictionary *dict1prime =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32EnumDictionary *dict3 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32EnumDictionary *dict4 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32EnumDictionary *dict2 =
+ [GPBInt32EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32EnumDictionary *dict = [GPBInt32EnumDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:700 forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const int32_t kValues[] = { 701, 702, 703 };
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 703);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 703);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:703 forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:701 forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 701);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const int32_t kValues2[] = { 702, 700 };
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 701);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Enum (Unknown Enums)
+
+@interface GPBInt32EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBInt32EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const int32_t kValues[] = { 700, 801, 702 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:13 rawValue:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:14 rawValue:NULL]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ if (i == 1) {
+ XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+ } else {
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const int32_t kValues1[] = { 700, 801, 702 }; // Unknown
+ const int32_t kValues2[] = { 700, 803, 702 }; // Unknown
+ const int32_t kValues3[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt32EnumDictionary *dict1 =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32EnumDictionary *dict1prime =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32EnumDictionary *dict3 =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32EnumDictionary *dict4 =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknown
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertEqualObjects(dict, dict2);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32EnumDictionary *dict2 =
+ [GPBInt32EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ [dict release];
+}
+
+- (void)testUnknownAdds {
+ GPBInt32EnumDictionary *dict =
+ [GPBInt32EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:12], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 0U);
+ [dict setRawValue:801 forKey:12]; // Unknown
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 11, 13, 14 };
+ const int32_t kValues[] = { 700, 702, 803 }; // Unknown
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ [dict2 release];
+}
+
+- (void)testUnknownRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:11 value:NULL]);
+ XCTAssertFalse([dict valueForKey:12 value:NULL]);
+ XCTAssertFalse([dict valueForKey:13 value:NULL]);
+ XCTAssertFalse([dict valueForKey:14 value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:11], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 value:NULL]);
+ XCTAssertTrue([dict valueForKey:11 value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:803 forKey:11]; // Unknown
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:14 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:700 forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:12 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:12 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:13 value:NULL]);
+ XCTAssertTrue([dict valueForKey:13 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 700);
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const int32_t kValues2[] = { 702, 801 }; // Unknown
+ GPBInt32EnumDictionary *dict2 =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:11 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:11 rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:12 value:NULL]);
+ XCTAssertTrue([dict valueForKey:12 value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:13 rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:13 rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:14 value:NULL]);
+ XCTAssertTrue([dict valueForKey:14 value:&value]);
+ XCTAssertEqual(value, 700);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopyUnknowns {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const int32_t kValues[] = { 700, 801, 702, 803 };
+ GPBInt32EnumDictionary *dict =
+ [[GPBInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int32 -> Object
+
+@interface GPBInt32ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt32ObjectDictionaryTests
+
+- (void)testEmpty {
+ GPBInt32ObjectDictionary *dict = [[GPBInt32ObjectDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:11]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt32ObjectDictionary *dict = [GPBInt32ObjectDictionary dictionaryWithValue:@"abc" forKey:11];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertNil([dict valueForKey:12]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, id aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 11);
+ XCTAssertEqualObjects(aValue, @"abc");
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int32_t kKeys[] = { 11, 12, 13 };
+ const id kValues[] = { @"abc", @"def", @"ghi" };
+ GPBInt32ObjectDictionary *dict =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:12], @"def");
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertNil([dict valueForKey:14]);
+
+ __block NSUInteger idx = 0;
+ int32_t *seenKeys = malloc(3 * sizeof(int32_t));
+ id *seenValues = malloc(3 * sizeof(id));
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, id aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqualObjects(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int32_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int32_t kKeys1[] = { 11, 12, 13, 14 };
+ const int32_t kKeys2[] = { 12, 11, 14 };
+ const id kValues1[] = { @"abc", @"def", @"ghi" };
+ const id kValues2[] = { @"abc", @"jkl", @"ghi" };
+ const id kValues3[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict1 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt32ObjectDictionary *dict1prime =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt32ObjectDictionary *dict2 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt32ObjectDictionary *dict3 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt32ObjectDictionary *dict4 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32ObjectDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt32ObjectDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt32ObjectDictionary *dict2 =
+ [GPBInt32ObjectDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt32ObjectDictionary *dict = [GPBInt32ObjectDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:@"abc" forKey:11];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int32_t kKeys[] = { 12, 13, 14 };
+ const id kValues[] = { @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict2 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:12], @"def");
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"jkl");
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertNil([dict valueForKey:12]);
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"jkl");
+
+ // Remove again does nothing.
+ [dict removeValueForKey:12];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertNil([dict valueForKey:12]);
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"jkl");
+
+ [dict removeValueForKey:14];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertNil([dict valueForKey:12]);
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertNil([dict valueForKey:14]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:11]);
+ XCTAssertNil([dict valueForKey:12]);
+ XCTAssertNil([dict valueForKey:13]);
+ XCTAssertNil([dict valueForKey:14]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int32_t kKeys[] = { 11, 12, 13, 14 };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt32ObjectDictionary *dict =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:12], @"def");
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"jkl");
+
+ [dict setValue:@"jkl" forKey:11];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:12], @"def");
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"jkl");
+
+ [dict setValue:@"def" forKey:14];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:12], @"def");
+ XCTAssertEqualObjects([dict valueForKey:13], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:14], @"def");
+
+ const int32_t kKeys2[] = { 12, 13 };
+ const id kValues2[] = { @"ghi", @"abc" };
+ GPBInt32ObjectDictionary *dict2 =
+ [[GPBInt32ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:11], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:12], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:13], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:14], @"def");
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14)
+
diff --git a/objectivec/Tests/GPBDictionaryTests+Int64.m b/objectivec/Tests/GPBDictionaryTests+Int64.m
new file mode 100644
index 00000000..6e794d38
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+Int64.m
@@ -0,0 +1,3650 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL)
+// This block of code is generated, do not edit it directly.
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int64_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 700:
+ case 701:
+ case 702:
+ case 703:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(int64_t)key {
+ // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+ // type correct.
+ return [[(GPBInt64EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const int64_t [])keys
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ forKeys:keys
+ count:count];
+}
+@end
+
+
+#pragma mark - Int64 -> UInt32
+
+@interface GPBInt64UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64UInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBInt64UInt32Dictionary *dict = [[GPBInt64UInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64UInt32Dictionary *dict = [GPBInt64UInt32Dictionary dictionaryWithValue:100U forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const uint32_t kValues[] = { 100U, 101U, 102U };
+ GPBInt64UInt32Dictionary *dict =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const uint32_t kValues1[] = { 100U, 101U, 102U };
+ const uint32_t kValues2[] = { 100U, 103U, 102U };
+ const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict1 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64UInt32Dictionary *dict1prime =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64UInt32Dictionary *dict2 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64UInt32Dictionary *dict3 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64UInt32Dictionary *dict4 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64UInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64UInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64UInt32Dictionary *dict2 =
+ [GPBInt64UInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64UInt32Dictionary *dict = [GPBInt64UInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const uint32_t kValues[] = { 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict2 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 103U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBInt64UInt32Dictionary *dict =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:103U forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:101U forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const uint32_t kValues2[] = { 102U, 100U };
+ GPBInt64UInt32Dictionary *dict2 =
+ [[GPBInt64UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Int32
+
+@interface GPBInt64Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64Int32DictionaryTests
+
+- (void)testEmpty {
+ GPBInt64Int32Dictionary *dict = [[GPBInt64Int32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64Int32Dictionary *dict = [GPBInt64Int32Dictionary dictionaryWithValue:200 forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const int32_t kValues[] = { 200, 201, 202 };
+ GPBInt64Int32Dictionary *dict =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const int32_t kValues1[] = { 200, 201, 202 };
+ const int32_t kValues2[] = { 200, 203, 202 };
+ const int32_t kValues3[] = { 200, 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict1 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64Int32Dictionary *dict1prime =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64Int32Dictionary *dict2 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64Int32Dictionary *dict3 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64Int32Dictionary *dict4 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64Int32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64Int32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64Int32Dictionary *dict2 =
+ [GPBInt64Int32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64Int32Dictionary *dict = [GPBInt64Int32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict2 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 203);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBInt64Int32Dictionary *dict =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:203 forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:201 forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 201);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const int32_t kValues2[] = { 202, 200 };
+ GPBInt64Int32Dictionary *dict2 =
+ [[GPBInt64Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> UInt64
+
+@interface GPBInt64UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64UInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBInt64UInt64Dictionary *dict = [[GPBInt64UInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64UInt64Dictionary *dict = [GPBInt64UInt64Dictionary dictionaryWithValue:300U forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const uint64_t kValues[] = { 300U, 301U, 302U };
+ GPBInt64UInt64Dictionary *dict =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const uint64_t kValues1[] = { 300U, 301U, 302U };
+ const uint64_t kValues2[] = { 300U, 303U, 302U };
+ const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict1 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64UInt64Dictionary *dict1prime =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64UInt64Dictionary *dict2 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64UInt64Dictionary *dict3 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64UInt64Dictionary *dict4 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64UInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64UInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64UInt64Dictionary *dict2 =
+ [GPBInt64UInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64UInt64Dictionary *dict = [GPBInt64UInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const uint64_t kValues[] = { 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict2 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 303U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBInt64UInt64Dictionary *dict =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:303U forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:301U forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const uint64_t kValues2[] = { 302U, 300U };
+ GPBInt64UInt64Dictionary *dict2 =
+ [[GPBInt64UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Int64
+
+@interface GPBInt64Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64Int64DictionaryTests
+
+- (void)testEmpty {
+ GPBInt64Int64Dictionary *dict = [[GPBInt64Int64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64Int64Dictionary *dict = [GPBInt64Int64Dictionary dictionaryWithValue:400 forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const int64_t kValues[] = { 400, 401, 402 };
+ GPBInt64Int64Dictionary *dict =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ int64_t *seenValues = malloc(3 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const int64_t kValues1[] = { 400, 401, 402 };
+ const int64_t kValues2[] = { 400, 403, 402 };
+ const int64_t kValues3[] = { 400, 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict1 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64Int64Dictionary *dict1prime =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64Int64Dictionary *dict2 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64Int64Dictionary *dict3 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64Int64Dictionary *dict4 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64Int64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64Int64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64Int64Dictionary *dict2 =
+ [GPBInt64Int64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64Int64Dictionary *dict = [GPBInt64Int64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const int64_t kValues[] = { 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict2 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 403);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBInt64Int64Dictionary *dict =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:403 forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:401 forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 401);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const int64_t kValues2[] = { 402, 400 };
+ GPBInt64Int64Dictionary *dict2 =
+ [[GPBInt64Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Bool
+
+@interface GPBInt64BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64BoolDictionaryTests
+
+- (void)testEmpty {
+ GPBInt64BoolDictionary *dict = [[GPBInt64BoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64BoolDictionary *dict = [GPBInt64BoolDictionary dictionaryWithValue:YES forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, YES);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const BOOL kValues[] = { YES, YES, NO };
+ GPBInt64BoolDictionary *dict =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ BOOL *seenValues = malloc(3 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const BOOL kValues1[] = { YES, YES, NO };
+ const BOOL kValues2[] = { YES, NO, NO };
+ const BOOL kValues3[] = { YES, YES, NO, NO };
+ GPBInt64BoolDictionary *dict1 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64BoolDictionary *dict1prime =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64BoolDictionary *dict2 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64BoolDictionary *dict3 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64BoolDictionary *dict4 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt64BoolDictionary *dict =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64BoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64BoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt64BoolDictionary *dict =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64BoolDictionary *dict2 =
+ [GPBInt64BoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64BoolDictionary *dict = [GPBInt64BoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:YES forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const BOOL kValues[] = { YES, NO, NO };
+ GPBInt64BoolDictionary *dict2 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, NO);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt64BoolDictionary *dict =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBInt64BoolDictionary *dict =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:NO forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:YES forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, YES);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const BOOL kValues2[] = { NO, YES };
+ GPBInt64BoolDictionary *dict2 =
+ [[GPBInt64BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Float
+
+@interface GPBInt64FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64FloatDictionaryTests
+
+- (void)testEmpty {
+ GPBInt64FloatDictionary *dict = [[GPBInt64FloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64FloatDictionary *dict = [GPBInt64FloatDictionary dictionaryWithValue:500.f forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const float kValues[] = { 500.f, 501.f, 502.f };
+ GPBInt64FloatDictionary *dict =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ float *seenValues = malloc(3 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const float kValues1[] = { 500.f, 501.f, 502.f };
+ const float kValues2[] = { 500.f, 503.f, 502.f };
+ const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict1 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64FloatDictionary *dict1prime =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64FloatDictionary *dict2 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64FloatDictionary *dict3 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64FloatDictionary *dict4 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64FloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64FloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64FloatDictionary *dict2 =
+ [GPBInt64FloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64FloatDictionary *dict = [GPBInt64FloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const float kValues[] = { 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict2 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBInt64FloatDictionary *dict =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ float value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:503.f forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:501.f forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const float kValues2[] = { 502.f, 500.f };
+ GPBInt64FloatDictionary *dict2 =
+ [[GPBInt64FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Double
+
+@interface GPBInt64DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64DoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBInt64DoubleDictionary *dict = [[GPBInt64DoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64DoubleDictionary *dict = [GPBInt64DoubleDictionary dictionaryWithValue:600. forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const double kValues[] = { 600., 601., 602. };
+ GPBInt64DoubleDictionary *dict =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ double *seenValues = malloc(3 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const double kValues1[] = { 600., 601., 602. };
+ const double kValues2[] = { 600., 603., 602. };
+ const double kValues3[] = { 600., 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict1 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64DoubleDictionary *dict1prime =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64DoubleDictionary *dict2 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64DoubleDictionary *dict3 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64DoubleDictionary *dict4 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64DoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64DoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64DoubleDictionary *dict2 =
+ [GPBInt64DoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64DoubleDictionary *dict = [GPBInt64DoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const double kValues[] = { 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict2 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 603.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBInt64DoubleDictionary *dict =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ double value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:603. forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:601. forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const double kValues2[] = { 602., 600. };
+ GPBInt64DoubleDictionary *dict2 =
+ [[GPBInt64DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Enum
+
+@interface GPBInt64EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64EnumDictionaryTests
+
+- (void)testEmpty {
+ GPBInt64EnumDictionary *dict = [[GPBInt64EnumDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64EnumDictionary *dict = [GPBInt64EnumDictionary dictionaryWithValue:700 forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqual(aValue, 700);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const int32_t kValues[] = { 700, 701, 702 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const int32_t kValues1[] = { 700, 701, 702 };
+ const int32_t kValues2[] = { 700, 703, 702 };
+ const int32_t kValues3[] = { 700, 701, 702, 703 };
+ GPBInt64EnumDictionary *dict1 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64EnumDictionary *dict1prime =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64EnumDictionary *dict3 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64EnumDictionary *dict4 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64EnumDictionary *dict2 =
+ [GPBInt64EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64EnumDictionary *dict = [GPBInt64EnumDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:700 forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 701, 702, 703 };
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 703);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:703 forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:701 forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 701);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const int32_t kValues2[] = { 702, 700 };
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 701);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Enum (Unknown Enums)
+
+@interface GPBInt64EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBInt64EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const int32_t kValues[] = { 700, 801, 702 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL rawValue:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:24LL rawValue:NULL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ if (i == 1) {
+ XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+ } else {
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const int32_t kValues1[] = { 700, 801, 702 }; // Unknown
+ const int32_t kValues2[] = { 700, 803, 702 }; // Unknown
+ const int32_t kValues3[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt64EnumDictionary *dict1 =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64EnumDictionary *dict1prime =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64EnumDictionary *dict3 =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64EnumDictionary *dict4 =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknown
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertEqualObjects(dict, dict2);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64EnumDictionary *dict2 =
+ [GPBInt64EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ [dict release];
+}
+
+- (void)testUnknownAdds {
+ GPBInt64EnumDictionary *dict =
+ [GPBInt64EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:22LL], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 0U);
+ [dict setRawValue:801 forKey:22LL]; // Unknown
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 21LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 702, 803 }; // Unknown
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ [dict2 release];
+}
+
+- (void)testUnknownRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:21LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:22LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:23LL value:NULL]);
+ XCTAssertFalse([dict valueForKey:24LL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:21LL], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:803 forKey:21LL]; // Unknown
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:700 forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:23LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 700);
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const int32_t kValues2[] = { 702, 801 }; // Unknown
+ GPBInt64EnumDictionary *dict2 =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:21LL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:22LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:22LL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:23LL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:23LL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:24LL value:NULL]);
+ XCTAssertTrue([dict valueForKey:24LL value:&value]);
+ XCTAssertEqual(value, 700);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopyUnknowns {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const int32_t kValues[] = { 700, 801, 702, 803 };
+ GPBInt64EnumDictionary *dict =
+ [[GPBInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - Int64 -> Object
+
+@interface GPBInt64ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBInt64ObjectDictionaryTests
+
+- (void)testEmpty {
+ GPBInt64ObjectDictionary *dict = [[GPBInt64ObjectDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:21LL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBInt64ObjectDictionary *dict = [GPBInt64ObjectDictionary dictionaryWithValue:@"abc" forKey:21LL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertNil([dict valueForKey:22LL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, id aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 21LL);
+ XCTAssertEqualObjects(aValue, @"abc");
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL };
+ const id kValues[] = { @"abc", @"def", @"ghi" };
+ GPBInt64ObjectDictionary *dict =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertNil([dict valueForKey:24LL]);
+
+ __block NSUInteger idx = 0;
+ int64_t *seenKeys = malloc(3 * sizeof(int64_t));
+ id *seenValues = malloc(3 * sizeof(id));
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, id aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqualObjects(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(int64_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const int64_t kKeys1[] = { 21LL, 22LL, 23LL, 24LL };
+ const int64_t kKeys2[] = { 22LL, 21LL, 24LL };
+ const id kValues1[] = { @"abc", @"def", @"ghi" };
+ const id kValues2[] = { @"abc", @"jkl", @"ghi" };
+ const id kValues3[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict1 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBInt64ObjectDictionary *dict1prime =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBInt64ObjectDictionary *dict2 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBInt64ObjectDictionary *dict3 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBInt64ObjectDictionary *dict4 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64ObjectDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBInt64ObjectDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBInt64ObjectDictionary *dict2 =
+ [GPBInt64ObjectDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBInt64ObjectDictionary *dict = [GPBInt64ObjectDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:@"abc" forKey:21LL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const int64_t kKeys[] = { 22LL, 23LL, 24LL };
+ const id kValues[] = { @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict2 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"jkl");
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertNil([dict valueForKey:22LL]);
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"jkl");
+
+ // Remove again does nothing.
+ [dict removeValueForKey:22LL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertNil([dict valueForKey:22LL]);
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"jkl");
+
+ [dict removeValueForKey:24LL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertNil([dict valueForKey:22LL]);
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertNil([dict valueForKey:24LL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:21LL]);
+ XCTAssertNil([dict valueForKey:22LL]);
+ XCTAssertNil([dict valueForKey:23LL]);
+ XCTAssertNil([dict valueForKey:24LL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const int64_t kKeys[] = { 21LL, 22LL, 23LL, 24LL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBInt64ObjectDictionary *dict =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"jkl");
+
+ [dict setValue:@"jkl" forKey:21LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"jkl");
+
+ [dict setValue:@"def" forKey:24LL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"def");
+
+ const int64_t kKeys2[] = { 22LL, 23LL };
+ const id kValues2[] = { @"ghi", @"abc" };
+ GPBInt64ObjectDictionary *dict2 =
+ [[GPBInt64ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:21LL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:22LL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:23LL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:24LL], @"def");
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL)
+
diff --git a/objectivec/Tests/GPBDictionaryTests+String.m b/objectivec/Tests/GPBDictionaryTests+String.m
new file mode 100644
index 00000000..95bf2d06
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+String.m
@@ -0,0 +1,3362 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble")
+// This block of code is generated, do not edit it directly.
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBStringEnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(NSString *)key;
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 700:
+ case 701:
+ case 702:
+ case 703:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBStringEnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(NSString *)key {
+ // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+ // type correct.
+ return [[(GPBStringEnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const NSString * [])keys
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ forKeys:keys
+ count:count];
+}
+@end
+
+
+#pragma mark - String -> UInt32
+
+@interface GPBStringUInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringUInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBStringUInt32Dictionary *dict = [[GPBStringUInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringUInt32Dictionary *dict = [GPBStringUInt32Dictionary dictionaryWithValue:100U forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const uint32_t kValues[] = { 100U, 101U, 102U };
+ GPBStringUInt32Dictionary *dict =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const uint32_t kValues1[] = { 100U, 101U, 102U };
+ const uint32_t kValues2[] = { 100U, 103U, 102U };
+ const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict1 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringUInt32Dictionary *dict1prime =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringUInt32Dictionary *dict2 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringUInt32Dictionary *dict3 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringUInt32Dictionary *dict4 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringUInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringUInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringUInt32Dictionary *dict2 =
+ [GPBStringUInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringUInt32Dictionary *dict = [GPBStringUInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const uint32_t kValues[] = { 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict2 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 103U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBStringUInt32Dictionary *dict =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:103U forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:101U forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const uint32_t kValues2[] = { 102U, 100U };
+ GPBStringUInt32Dictionary *dict2 =
+ [[GPBStringUInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Int32
+
+@interface GPBStringInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBStringInt32Dictionary *dict = [[GPBStringInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringInt32Dictionary *dict = [GPBStringInt32Dictionary dictionaryWithValue:200 forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const int32_t kValues[] = { 200, 201, 202 };
+ GPBStringInt32Dictionary *dict =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const int32_t kValues1[] = { 200, 201, 202 };
+ const int32_t kValues2[] = { 200, 203, 202 };
+ const int32_t kValues3[] = { 200, 201, 202, 203 };
+ GPBStringInt32Dictionary *dict1 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringInt32Dictionary *dict1prime =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringInt32Dictionary *dict2 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringInt32Dictionary *dict3 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringInt32Dictionary *dict4 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBStringInt32Dictionary *dict =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBStringInt32Dictionary *dict =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringInt32Dictionary *dict2 =
+ [GPBStringInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringInt32Dictionary *dict = [GPBStringInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 201, 202, 203 };
+ GPBStringInt32Dictionary *dict2 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 203);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBStringInt32Dictionary *dict =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 203);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBStringInt32Dictionary *dict =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:203 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:201 forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 201);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const int32_t kValues2[] = { 202, 200 };
+ GPBStringInt32Dictionary *dict2 =
+ [[GPBStringInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> UInt64
+
+@interface GPBStringUInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringUInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBStringUInt64Dictionary *dict = [[GPBStringUInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringUInt64Dictionary *dict = [GPBStringUInt64Dictionary dictionaryWithValue:300U forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const uint64_t kValues[] = { 300U, 301U, 302U };
+ GPBStringUInt64Dictionary *dict =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const uint64_t kValues1[] = { 300U, 301U, 302U };
+ const uint64_t kValues2[] = { 300U, 303U, 302U };
+ const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict1 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringUInt64Dictionary *dict1prime =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringUInt64Dictionary *dict2 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringUInt64Dictionary *dict3 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringUInt64Dictionary *dict4 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringUInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringUInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringUInt64Dictionary *dict2 =
+ [GPBStringUInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringUInt64Dictionary *dict = [GPBStringUInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const uint64_t kValues[] = { 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict2 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 303U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBStringUInt64Dictionary *dict =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:303U forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:301U forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const uint64_t kValues2[] = { 302U, 300U };
+ GPBStringUInt64Dictionary *dict2 =
+ [[GPBStringUInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Int64
+
+@interface GPBStringInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBStringInt64Dictionary *dict = [[GPBStringInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringInt64Dictionary *dict = [GPBStringInt64Dictionary dictionaryWithValue:400 forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const int64_t kValues[] = { 400, 401, 402 };
+ GPBStringInt64Dictionary *dict =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ int64_t *seenValues = malloc(3 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const int64_t kValues1[] = { 400, 401, 402 };
+ const int64_t kValues2[] = { 400, 403, 402 };
+ const int64_t kValues3[] = { 400, 401, 402, 403 };
+ GPBStringInt64Dictionary *dict1 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringInt64Dictionary *dict1prime =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringInt64Dictionary *dict2 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringInt64Dictionary *dict3 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringInt64Dictionary *dict4 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBStringInt64Dictionary *dict =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBStringInt64Dictionary *dict =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringInt64Dictionary *dict2 =
+ [GPBStringInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringInt64Dictionary *dict = [GPBStringInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const int64_t kValues[] = { 401, 402, 403 };
+ GPBStringInt64Dictionary *dict2 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 403);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBStringInt64Dictionary *dict =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 403);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBStringInt64Dictionary *dict =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:403 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:401 forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 401);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const int64_t kValues2[] = { 402, 400 };
+ GPBStringInt64Dictionary *dict2 =
+ [[GPBStringInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Bool
+
+@interface GPBStringBoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringBoolDictionaryTests
+
+- (void)testEmpty {
+ GPBStringBoolDictionary *dict = [[GPBStringBoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringBoolDictionary *dict = [GPBStringBoolDictionary dictionaryWithValue:YES forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, YES);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const BOOL kValues[] = { YES, YES, NO };
+ GPBStringBoolDictionary *dict =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ BOOL *seenValues = malloc(3 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const BOOL kValues1[] = { YES, YES, NO };
+ const BOOL kValues2[] = { YES, NO, NO };
+ const BOOL kValues3[] = { YES, YES, NO, NO };
+ GPBStringBoolDictionary *dict1 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringBoolDictionary *dict1prime =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringBoolDictionary *dict2 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringBoolDictionary *dict3 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringBoolDictionary *dict4 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBStringBoolDictionary *dict =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringBoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringBoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBStringBoolDictionary *dict =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringBoolDictionary *dict2 =
+ [GPBStringBoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringBoolDictionary *dict = [GPBStringBoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:YES forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const BOOL kValues[] = { YES, NO, NO };
+ GPBStringBoolDictionary *dict2 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, NO);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBStringBoolDictionary *dict =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, NO);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBStringBoolDictionary *dict =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:NO forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:YES forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, YES);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const BOOL kValues2[] = { NO, YES };
+ GPBStringBoolDictionary *dict2 =
+ [[GPBStringBoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Float
+
+@interface GPBStringFloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringFloatDictionaryTests
+
+- (void)testEmpty {
+ GPBStringFloatDictionary *dict = [[GPBStringFloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringFloatDictionary *dict = [GPBStringFloatDictionary dictionaryWithValue:500.f forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const float kValues[] = { 500.f, 501.f, 502.f };
+ GPBStringFloatDictionary *dict =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ float *seenValues = malloc(3 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const float kValues1[] = { 500.f, 501.f, 502.f };
+ const float kValues2[] = { 500.f, 503.f, 502.f };
+ const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict1 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringFloatDictionary *dict1prime =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringFloatDictionary *dict2 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringFloatDictionary *dict3 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringFloatDictionary *dict4 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringFloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringFloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringFloatDictionary *dict2 =
+ [GPBStringFloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringFloatDictionary *dict = [GPBStringFloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const float kValues[] = { 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict2 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 503.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBStringFloatDictionary *dict =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ float value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:503.f forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:501.f forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const float kValues2[] = { 502.f, 500.f };
+ GPBStringFloatDictionary *dict2 =
+ [[GPBStringFloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Double
+
+@interface GPBStringDoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringDoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBStringDoubleDictionary *dict = [[GPBStringDoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringDoubleDictionary *dict = [GPBStringDoubleDictionary dictionaryWithValue:600. forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const double kValues[] = { 600., 601., 602. };
+ GPBStringDoubleDictionary *dict =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ double *seenValues = malloc(3 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const double kValues1[] = { 600., 601., 602. };
+ const double kValues2[] = { 600., 603., 602. };
+ const double kValues3[] = { 600., 601., 602., 603. };
+ GPBStringDoubleDictionary *dict1 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringDoubleDictionary *dict1prime =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringDoubleDictionary *dict2 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringDoubleDictionary *dict3 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringDoubleDictionary *dict4 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBStringDoubleDictionary *dict =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringDoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringDoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBStringDoubleDictionary *dict =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringDoubleDictionary *dict2 =
+ [GPBStringDoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringDoubleDictionary *dict = [GPBStringDoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const double kValues[] = { 601., 602., 603. };
+ GPBStringDoubleDictionary *dict2 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 603.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBStringDoubleDictionary *dict =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBStringDoubleDictionary *dict =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ double value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:603. forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:601. forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const double kValues2[] = { 602., 600. };
+ GPBStringDoubleDictionary *dict2 =
+ [[GPBStringDoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Enum
+
+@interface GPBStringEnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBStringEnumDictionaryTests
+
+- (void)testEmpty {
+ GPBStringEnumDictionary *dict = [[GPBStringEnumDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBStringEnumDictionary *dict = [GPBStringEnumDictionary dictionaryWithValue:700 forKey:@"foo"];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqualObjects(aKey, @"foo");
+ XCTAssertEqual(aValue, 700);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const int32_t kValues[] = { 700, 701, 702 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const int32_t kValues1[] = { 700, 701, 702 };
+ const int32_t kValues2[] = { 700, 703, 702 };
+ const int32_t kValues3[] = { 700, 701, 702, 703 };
+ GPBStringEnumDictionary *dict1 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringEnumDictionary *dict1prime =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringEnumDictionary *dict3 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringEnumDictionary *dict4 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringEnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringEnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringEnumDictionary *dict2 =
+ [GPBStringEnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBStringEnumDictionary *dict = [GPBStringEnumDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:700 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 701, 702, 703 };
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 703);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 703);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:703 forKey:@"foo"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:701 forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 701);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const int32_t kValues2[] = { 702, 700 };
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 701);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - String -> Enum (Unknown Enums)
+
+@interface GPBStringEnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBStringEnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz" };
+ const int32_t kValues[] = { 700, 801, 702 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" rawValue:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:@"mumble" rawValue:NULL]);
+
+ __block NSUInteger idx = 0;
+ NSString **seenKeys = malloc(3 * sizeof(NSString*));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ if (i == 1) {
+ XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+ } else {
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if ([kKeys[i] isEqual:seenKeys[j]]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+ const NSString *kKeys1[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const NSString *kKeys2[] = { @"bar", @"foo", @"mumble" };
+ const int32_t kValues1[] = { 700, 801, 702 }; // Unknown
+ const int32_t kValues2[] = { 700, 803, 702 }; // Unknown
+ const int32_t kValues3[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBStringEnumDictionary *dict1 =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBStringEnumDictionary *dict1prime =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBStringEnumDictionary *dict3 =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBStringEnumDictionary *dict4 =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknown
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringEnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertEqualObjects(dict, dict2);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringEnumDictionary *dict2 =
+ [GPBStringEnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ [dict release];
+}
+
+- (void)testUnknownAdds {
+ GPBStringEnumDictionary *dict =
+ [GPBStringEnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:@"bar"], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 0U);
+ [dict setRawValue:801 forKey:@"bar"]; // Unknown
+ XCTAssertEqual(dict.count, 1U);
+
+ const NSString *kKeys[] = { @"foo", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 702, 803 }; // Unknown
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ [dict2 release];
+}
+
+- (void)testUnknownRemove {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:@"bar"];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict removeValueForKey:@"mumble"];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertFalse([dict valueForKey:@"mumble" value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:@"foo"], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:803 forKey:@"foo"]; // Unknown
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:700 forKey:@"mumble"];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"baz" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 700);
+
+ const NSString *kKeys2[] = { @"bar", @"baz" };
+ const int32_t kValues2[] = { 702, 801 }; // Unknown
+ GPBStringEnumDictionary *dict2 =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"foo" rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:@"bar" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"bar" value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:@"baz" rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:@"baz" rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:NULL]);
+ XCTAssertTrue([dict valueForKey:@"mumble" value:&value]);
+ XCTAssertEqual(value, 700);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopyUnknowns {
+ const NSString *kKeys[] = { @"foo", @"bar", @"baz", @"mumble" };
+ const int32_t kValues[] = { 700, 801, 702, 803 };
+ GPBStringEnumDictionary *dict =
+ [[GPBStringEnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBStringEnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertTrue([dict2 isKindOfClass:[GPBStringEnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble")
+
diff --git a/objectivec/Tests/GPBDictionaryTests+UInt32.m b/objectivec/Tests/GPBDictionaryTests+UInt32.m
new file mode 100644
index 00000000..a89ded3d
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+UInt32.m
@@ -0,0 +1,3650 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U)
+// This block of code is generated, do not edit it directly.
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBUInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint32_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 700:
+ case 701:
+ case 702:
+ case 703:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBUInt32EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint32_t)key {
+ // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+ // type correct.
+ return [[(GPBUInt32EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint32_t [])keys
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ forKeys:keys
+ count:count];
+}
+@end
+
+
+#pragma mark - UInt32 -> UInt32
+
+@interface GPBUInt32UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32UInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32UInt32Dictionary *dict = [[GPBUInt32UInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32UInt32Dictionary *dict = [GPBUInt32UInt32Dictionary dictionaryWithValue:100U forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const uint32_t kValues[] = { 100U, 101U, 102U };
+ GPBUInt32UInt32Dictionary *dict =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const uint32_t kValues1[] = { 100U, 101U, 102U };
+ const uint32_t kValues2[] = { 100U, 103U, 102U };
+ const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict1 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32UInt32Dictionary *dict1prime =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32UInt32Dictionary *dict2 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32UInt32Dictionary *dict3 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32UInt32Dictionary *dict4 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32UInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32UInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32UInt32Dictionary *dict2 =
+ [GPBUInt32UInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32UInt32Dictionary *dict = [GPBUInt32UInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const uint32_t kValues[] = { 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict2 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 103U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt32UInt32Dictionary *dict =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:103U forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:101U forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const uint32_t kValues2[] = { 102U, 100U };
+ GPBUInt32UInt32Dictionary *dict2 =
+ [[GPBUInt32UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Int32
+
+@interface GPBUInt32Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32Int32DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32Int32Dictionary *dict = [[GPBUInt32Int32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32Int32Dictionary *dict = [GPBUInt32Int32Dictionary dictionaryWithValue:200 forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const int32_t kValues[] = { 200, 201, 202 };
+ GPBUInt32Int32Dictionary *dict =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const int32_t kValues1[] = { 200, 201, 202 };
+ const int32_t kValues2[] = { 200, 203, 202 };
+ const int32_t kValues3[] = { 200, 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict1 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32Int32Dictionary *dict1prime =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32Int32Dictionary *dict2 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32Int32Dictionary *dict3 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32Int32Dictionary *dict4 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32Int32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32Int32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32Int32Dictionary *dict2 =
+ [GPBUInt32Int32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32Int32Dictionary *dict = [GPBUInt32Int32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const int32_t kValues[] = { 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict2 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 203);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 203);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt32Int32Dictionary *dict =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:203 forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:201 forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 201);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const int32_t kValues2[] = { 202, 200 };
+ GPBUInt32Int32Dictionary *dict2 =
+ [[GPBUInt32Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> UInt64
+
+@interface GPBUInt32UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32UInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32UInt64Dictionary *dict = [[GPBUInt32UInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32UInt64Dictionary *dict = [GPBUInt32UInt64Dictionary dictionaryWithValue:300U forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const uint64_t kValues[] = { 300U, 301U, 302U };
+ GPBUInt32UInt64Dictionary *dict =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const uint64_t kValues1[] = { 300U, 301U, 302U };
+ const uint64_t kValues2[] = { 300U, 303U, 302U };
+ const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict1 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32UInt64Dictionary *dict1prime =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32UInt64Dictionary *dict2 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32UInt64Dictionary *dict3 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32UInt64Dictionary *dict4 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32UInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32UInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32UInt64Dictionary *dict2 =
+ [GPBUInt32UInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32UInt64Dictionary *dict = [GPBUInt32UInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const uint64_t kValues[] = { 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict2 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 303U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt32UInt64Dictionary *dict =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:303U forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:301U forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const uint64_t kValues2[] = { 302U, 300U };
+ GPBUInt32UInt64Dictionary *dict2 =
+ [[GPBUInt32UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Int64
+
+@interface GPBUInt32Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32Int64DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32Int64Dictionary *dict = [[GPBUInt32Int64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32Int64Dictionary *dict = [GPBUInt32Int64Dictionary dictionaryWithValue:400 forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const int64_t kValues[] = { 400, 401, 402 };
+ GPBUInt32Int64Dictionary *dict =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ int64_t *seenValues = malloc(3 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const int64_t kValues1[] = { 400, 401, 402 };
+ const int64_t kValues2[] = { 400, 403, 402 };
+ const int64_t kValues3[] = { 400, 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict1 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32Int64Dictionary *dict1prime =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32Int64Dictionary *dict2 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32Int64Dictionary *dict3 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32Int64Dictionary *dict4 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32Int64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32Int64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32Int64Dictionary *dict2 =
+ [GPBUInt32Int64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32Int64Dictionary *dict = [GPBUInt32Int64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const int64_t kValues[] = { 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict2 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 403);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 403);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt32Int64Dictionary *dict =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:403 forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:401 forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 401);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const int64_t kValues2[] = { 402, 400 };
+ GPBUInt32Int64Dictionary *dict2 =
+ [[GPBUInt32Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Bool
+
+@interface GPBUInt32BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32BoolDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32BoolDictionary *dict = [[GPBUInt32BoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32BoolDictionary *dict = [GPBUInt32BoolDictionary dictionaryWithValue:YES forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, YES);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const BOOL kValues[] = { YES, YES, NO };
+ GPBUInt32BoolDictionary *dict =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ BOOL *seenValues = malloc(3 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const BOOL kValues1[] = { YES, YES, NO };
+ const BOOL kValues2[] = { YES, NO, NO };
+ const BOOL kValues3[] = { YES, YES, NO, NO };
+ GPBUInt32BoolDictionary *dict1 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32BoolDictionary *dict1prime =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32BoolDictionary *dict2 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32BoolDictionary *dict3 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32BoolDictionary *dict4 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt32BoolDictionary *dict =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32BoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32BoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt32BoolDictionary *dict =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32BoolDictionary *dict2 =
+ [GPBUInt32BoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32BoolDictionary *dict = [GPBUInt32BoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:YES forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const BOOL kValues[] = { YES, NO, NO };
+ GPBUInt32BoolDictionary *dict2 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, NO);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt32BoolDictionary *dict =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, NO);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt32BoolDictionary *dict =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:NO forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:YES forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, YES);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const BOOL kValues2[] = { NO, YES };
+ GPBUInt32BoolDictionary *dict2 =
+ [[GPBUInt32BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Float
+
+@interface GPBUInt32FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32FloatDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32FloatDictionary *dict = [[GPBUInt32FloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32FloatDictionary *dict = [GPBUInt32FloatDictionary dictionaryWithValue:500.f forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const float kValues[] = { 500.f, 501.f, 502.f };
+ GPBUInt32FloatDictionary *dict =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ float *seenValues = malloc(3 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const float kValues1[] = { 500.f, 501.f, 502.f };
+ const float kValues2[] = { 500.f, 503.f, 502.f };
+ const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict1 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32FloatDictionary *dict1prime =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32FloatDictionary *dict2 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32FloatDictionary *dict3 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32FloatDictionary *dict4 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32FloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32FloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32FloatDictionary *dict2 =
+ [GPBUInt32FloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32FloatDictionary *dict = [GPBUInt32FloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const float kValues[] = { 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict2 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 503.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt32FloatDictionary *dict =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ float value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:503.f forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:501.f forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const float kValues2[] = { 502.f, 500.f };
+ GPBUInt32FloatDictionary *dict2 =
+ [[GPBUInt32FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Double
+
+@interface GPBUInt32DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32DoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32DoubleDictionary *dict = [[GPBUInt32DoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32DoubleDictionary *dict = [GPBUInt32DoubleDictionary dictionaryWithValue:600. forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const double kValues[] = { 600., 601., 602. };
+ GPBUInt32DoubleDictionary *dict =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ double *seenValues = malloc(3 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const double kValues1[] = { 600., 601., 602. };
+ const double kValues2[] = { 600., 603., 602. };
+ const double kValues3[] = { 600., 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict1 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32DoubleDictionary *dict1prime =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32DoubleDictionary *dict2 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32DoubleDictionary *dict3 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32DoubleDictionary *dict4 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32DoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32DoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32DoubleDictionary *dict2 =
+ [GPBUInt32DoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32DoubleDictionary *dict = [GPBUInt32DoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const double kValues[] = { 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict2 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 603.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt32DoubleDictionary *dict =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ double value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:603. forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:601. forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const double kValues2[] = { 602., 600. };
+ GPBUInt32DoubleDictionary *dict2 =
+ [[GPBUInt32DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Enum
+
+@interface GPBUInt32EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32EnumDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32EnumDictionary *dict = [[GPBUInt32EnumDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32EnumDictionary *dict = [GPBUInt32EnumDictionary dictionaryWithValue:700 forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqual(aValue, 700);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const int32_t kValues[] = { 700, 701, 702 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const int32_t kValues1[] = { 700, 701, 702 };
+ const int32_t kValues2[] = { 700, 703, 702 };
+ const int32_t kValues3[] = { 700, 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict1 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32EnumDictionary *dict1prime =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32EnumDictionary *dict3 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32EnumDictionary *dict4 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32EnumDictionary *dict2 =
+ [GPBUInt32EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32EnumDictionary *dict = [GPBUInt32EnumDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:700 forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const int32_t kValues[] = { 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 703);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 703);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:703 forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:701 forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 701);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const int32_t kValues2[] = { 702, 700 };
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 701);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Enum (Unknown Enums)
+
+@interface GPBUInt32EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBUInt32EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const int32_t kValues[] = { 700, 801, 702 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:3U rawValue:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:4U rawValue:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ if (i == 1) {
+ XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+ } else {
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const int32_t kValues1[] = { 700, 801, 702 }; // Unknown
+ const int32_t kValues2[] = { 700, 803, 702 }; // Unknown
+ const int32_t kValues3[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt32EnumDictionary *dict1 =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32EnumDictionary *dict1prime =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32EnumDictionary *dict3 =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32EnumDictionary *dict4 =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknown
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertEqualObjects(dict, dict2);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32EnumDictionary *dict2 =
+ [GPBUInt32EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ [dict release];
+}
+
+- (void)testUnknownAdds {
+ GPBUInt32EnumDictionary *dict =
+ [GPBUInt32EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:2U], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 0U);
+ [dict setRawValue:801 forKey:2U]; // Unknown
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 1U, 3U, 4U };
+ const int32_t kValues[] = { 700, 702, 803 }; // Unknown
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ [dict2 release];
+}
+
+- (void)testUnknownRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:1U value:NULL]);
+ XCTAssertFalse([dict valueForKey:2U value:NULL]);
+ XCTAssertFalse([dict valueForKey:3U value:NULL]);
+ XCTAssertFalse([dict valueForKey:4U value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:1U], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U value:NULL]);
+ XCTAssertTrue([dict valueForKey:1U value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:803 forKey:1U]; // Unknown
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:4U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:700 forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:2U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:2U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:3U value:NULL]);
+ XCTAssertTrue([dict valueForKey:3U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 700);
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const int32_t kValues2[] = { 702, 801 }; // Unknown
+ GPBUInt32EnumDictionary *dict2 =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:1U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:1U rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:2U value:NULL]);
+ XCTAssertTrue([dict valueForKey:2U value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:3U rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:3U rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:4U value:NULL]);
+ XCTAssertTrue([dict valueForKey:4U value:&value]);
+ XCTAssertEqual(value, 700);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopyUnknowns {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const int32_t kValues[] = { 700, 801, 702, 803 };
+ GPBUInt32EnumDictionary *dict =
+ [[GPBUInt32EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt32 -> Object
+
+@interface GPBUInt32ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt32ObjectDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt32ObjectDictionary *dict = [[GPBUInt32ObjectDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:1U]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt32ObjectDictionary *dict = [GPBUInt32ObjectDictionary dictionaryWithValue:@"abc" forKey:1U];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertNil([dict valueForKey:2U]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, id aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 1U);
+ XCTAssertEqualObjects(aValue, @"abc");
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint32_t kKeys[] = { 1U, 2U, 3U };
+ const id kValues[] = { @"abc", @"def", @"ghi" };
+ GPBUInt32ObjectDictionary *dict =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"def");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertNil([dict valueForKey:4U]);
+
+ __block NSUInteger idx = 0;
+ uint32_t *seenKeys = malloc(3 * sizeof(uint32_t));
+ id *seenValues = malloc(3 * sizeof(id));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, id aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqualObjects(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint32_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint32_t kKeys1[] = { 1U, 2U, 3U, 4U };
+ const uint32_t kKeys2[] = { 2U, 1U, 4U };
+ const id kValues1[] = { @"abc", @"def", @"ghi" };
+ const id kValues2[] = { @"abc", @"jkl", @"ghi" };
+ const id kValues3[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict1 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt32ObjectDictionary *dict1prime =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt32ObjectDictionary *dict2 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt32ObjectDictionary *dict3 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt32ObjectDictionary *dict4 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32ObjectDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt32ObjectDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt32ObjectDictionary *dict2 =
+ [GPBUInt32ObjectDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt32ObjectDictionary *dict = [GPBUInt32ObjectDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:@"abc" forKey:1U];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint32_t kKeys[] = { 2U, 3U, 4U };
+ const id kValues[] = { @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict2 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"def");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"jkl");
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertNil([dict valueForKey:2U]);
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"jkl");
+
+ // Remove again does nothing.
+ [dict removeValueForKey:2U];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertNil([dict valueForKey:2U]);
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"jkl");
+
+ [dict removeValueForKey:4U];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertNil([dict valueForKey:2U]);
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertNil([dict valueForKey:4U]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:1U]);
+ XCTAssertNil([dict valueForKey:2U]);
+ XCTAssertNil([dict valueForKey:3U]);
+ XCTAssertNil([dict valueForKey:4U]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint32_t kKeys[] = { 1U, 2U, 3U, 4U };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt32ObjectDictionary *dict =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"def");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"jkl");
+
+ [dict setValue:@"jkl" forKey:1U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"def");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"jkl");
+
+ [dict setValue:@"def" forKey:4U];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"def");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"def");
+
+ const uint32_t kKeys2[] = { 2U, 3U };
+ const id kValues2[] = { @"ghi", @"abc" };
+ GPBUInt32ObjectDictionary *dict2 =
+ [[GPBUInt32ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:1U], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:2U], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:3U], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:4U], @"def");
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U)
+
diff --git a/objectivec/Tests/GPBDictionaryTests+UInt64.m b/objectivec/Tests/GPBDictionaryTests+UInt64.m
new file mode 100644
index 00000000..355639c6
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests+UInt64.m
@@ -0,0 +1,3649 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+
+// Pull in the macros (using an external file because expanding all tests
+// in a single file makes a file that is failing to work with within Xcode.
+//%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
+
+//%PDDM-EXPAND TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL)
+// This block of code is generated, do not edit it directly.
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+// To let the testing macros work, add some extra methods to simplify things.
+@interface GPBUInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint64_t)key;
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count;
+@end
+
+static BOOL TestingEnum_IsValidValue(int32_t value) {
+ switch (value) {
+ case 700:
+ case 701:
+ case 702:
+ case 703:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+@implementation GPBUInt64EnumDictionary (TestingTweak)
++ (instancetype)dictionaryWithValue:(int32_t)value forKey:(uint64_t)key {
+ // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+ // type correct.
+ return [[(GPBUInt64EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:&value
+ forKeys:&key
+ count:1] autorelease];
+}
+- (instancetype)initWithValues:(const int32_t [])values
+ forKeys:(const uint64_t [])keys
+ count:(NSUInteger)count {
+ return [self initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:values
+ forKeys:keys
+ count:count];
+}
+@end
+
+
+#pragma mark - UInt64 -> UInt32
+
+@interface GPBUInt64UInt32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64UInt32DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64UInt32Dictionary *dict = [[GPBUInt64UInt32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64UInt32Dictionary *dict = [GPBUInt64UInt32Dictionary dictionaryWithValue:100U forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 100U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const uint32_t kValues[] = { 100U, 101U, 102U };
+ GPBUInt64UInt32Dictionary *dict =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ uint32_t *seenValues = malloc(3 * sizeof(uint32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const uint32_t kValues1[] = { 100U, 101U, 102U };
+ const uint32_t kValues2[] = { 100U, 103U, 102U };
+ const uint32_t kValues3[] = { 100U, 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict1 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64UInt32Dictionary *dict1prime =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64UInt32Dictionary *dict2 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64UInt32Dictionary *dict3 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64UInt32Dictionary *dict4 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64UInt32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64UInt32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64UInt32Dictionary *dict2 =
+ [GPBUInt64UInt32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64UInt32Dictionary *dict = [GPBUInt64UInt32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:100U forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const uint32_t kValues[] = { 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict2 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint32_t kValues[] = { 100U, 101U, 102U, 103U };
+ GPBUInt64UInt32Dictionary *dict =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:103U forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+
+ [dict setValue:101U forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const uint32_t kValues2[] = { 102U, 100U };
+ GPBUInt64UInt32Dictionary *dict2 =
+ [[GPBUInt64UInt32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 103U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 102U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 100U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 101U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Int32
+
+@interface GPBUInt64Int32DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64Int32DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64Int32Dictionary *dict = [[GPBUInt64Int32Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64Int32Dictionary *dict = [GPBUInt64Int32Dictionary dictionaryWithValue:200 forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 200);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const int32_t kValues[] = { 200, 201, 202 };
+ GPBUInt64Int32Dictionary *dict =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const int32_t kValues1[] = { 200, 201, 202 };
+ const int32_t kValues2[] = { 200, 203, 202 };
+ const int32_t kValues3[] = { 200, 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict1 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64Int32Dictionary *dict1prime =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64Int32Dictionary *dict2 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64Int32Dictionary *dict3 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64Int32Dictionary *dict4 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64Int32Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64Int32Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64Int32Dictionary *dict2 =
+ [GPBUInt64Int32Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64Int32Dictionary *dict = [GPBUInt64Int32Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:200 forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict2 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 203);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 200, 201, 202, 203 };
+ GPBUInt64Int32Dictionary *dict =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:203 forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 203);
+
+ [dict setValue:201 forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 201);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 201);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const int32_t kValues2[] = { 202, 200 };
+ GPBUInt64Int32Dictionary *dict2 =
+ [[GPBUInt64Int32Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 203);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 202);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 200);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 201);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> UInt64
+
+@interface GPBUInt64UInt64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64UInt64DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64UInt64Dictionary *dict = [[GPBUInt64UInt64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64UInt64Dictionary *dict = [GPBUInt64UInt64Dictionary dictionaryWithValue:300U forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 300U);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const uint64_t kValues[] = { 300U, 301U, 302U };
+ GPBUInt64UInt64Dictionary *dict =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ uint64_t *seenValues = malloc(3 * sizeof(uint64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const uint64_t kValues1[] = { 300U, 301U, 302U };
+ const uint64_t kValues2[] = { 300U, 303U, 302U };
+ const uint64_t kValues3[] = { 300U, 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict1 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64UInt64Dictionary *dict1prime =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64UInt64Dictionary *dict2 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64UInt64Dictionary *dict3 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64UInt64Dictionary *dict4 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64UInt64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64UInt64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64UInt64Dictionary *dict2 =
+ [GPBUInt64UInt64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64UInt64Dictionary *dict = [GPBUInt64UInt64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:300U forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const uint64_t kValues[] = { 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict2 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kValues[] = { 300U, 301U, 302U, 303U };
+ GPBUInt64UInt64Dictionary *dict =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ uint64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:303U forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+
+ [dict setValue:301U forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const uint64_t kValues2[] = { 302U, 300U };
+ GPBUInt64UInt64Dictionary *dict2 =
+ [[GPBUInt64UInt64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 303U);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 302U);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 300U);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 301U);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Int64
+
+@interface GPBUInt64Int64DictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64Int64DictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64Int64Dictionary *dict = [[GPBUInt64Int64Dictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64Int64Dictionary *dict = [GPBUInt64Int64Dictionary dictionaryWithValue:400 forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 400);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const int64_t kValues[] = { 400, 401, 402 };
+ GPBUInt64Int64Dictionary *dict =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ int64_t *seenValues = malloc(3 * sizeof(int64_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const int64_t kValues1[] = { 400, 401, 402 };
+ const int64_t kValues2[] = { 400, 403, 402 };
+ const int64_t kValues3[] = { 400, 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict1 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64Int64Dictionary *dict1prime =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64Int64Dictionary *dict2 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64Int64Dictionary *dict3 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64Int64Dictionary *dict4 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64Int64Dictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64Int64Dictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64Int64Dictionary *dict2 =
+ [GPBUInt64Int64Dictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64Int64Dictionary *dict = [GPBUInt64Int64Dictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:400 forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const int64_t kValues[] = { 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict2 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 403);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int64_t kValues[] = { 400, 401, 402, 403 };
+ GPBUInt64Int64Dictionary *dict =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int64_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:403 forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 403);
+
+ [dict setValue:401 forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 401);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 401);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const int64_t kValues2[] = { 402, 400 };
+ GPBUInt64Int64Dictionary *dict2 =
+ [[GPBUInt64Int64Dictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 403);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 402);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 400);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 401);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Bool
+
+@interface GPBUInt64BoolDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64BoolDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64BoolDictionary *dict = [[GPBUInt64BoolDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64BoolDictionary *dict = [GPBUInt64BoolDictionary dictionaryWithValue:YES forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, YES);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const BOOL kValues[] = { YES, YES, NO };
+ GPBUInt64BoolDictionary *dict =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ BOOL *seenValues = malloc(3 * sizeof(BOOL));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const BOOL kValues1[] = { YES, YES, NO };
+ const BOOL kValues2[] = { YES, NO, NO };
+ const BOOL kValues3[] = { YES, YES, NO, NO };
+ GPBUInt64BoolDictionary *dict1 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64BoolDictionary *dict1prime =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64BoolDictionary *dict2 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64BoolDictionary *dict3 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64BoolDictionary *dict4 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt64BoolDictionary *dict =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64BoolDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64BoolDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt64BoolDictionary *dict =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64BoolDictionary *dict2 =
+ [GPBUInt64BoolDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64BoolDictionary *dict = [GPBUInt64BoolDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:YES forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const BOOL kValues[] = { YES, NO, NO };
+ GPBUInt64BoolDictionary *dict2 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt64BoolDictionary *dict =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const BOOL kValues[] = { YES, YES, NO, NO };
+ GPBUInt64BoolDictionary *dict =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ BOOL value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:NO forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, NO);
+
+ [dict setValue:YES forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, YES);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const BOOL kValues2[] = { NO, YES };
+ GPBUInt64BoolDictionary *dict2 =
+ [[GPBUInt64BoolDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, NO);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, YES);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, YES);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Float
+
+@interface GPBUInt64FloatDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64FloatDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64FloatDictionary *dict = [[GPBUInt64FloatDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64FloatDictionary *dict = [GPBUInt64FloatDictionary dictionaryWithValue:500.f forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ float value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 500.f);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const float kValues[] = { 500.f, 501.f, 502.f };
+ GPBUInt64FloatDictionary *dict =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ float *seenValues = malloc(3 * sizeof(float));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const float kValues1[] = { 500.f, 501.f, 502.f };
+ const float kValues2[] = { 500.f, 503.f, 502.f };
+ const float kValues3[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict1 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64FloatDictionary *dict1prime =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64FloatDictionary *dict2 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64FloatDictionary *dict3 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64FloatDictionary *dict4 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64FloatDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64FloatDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64FloatDictionary *dict2 =
+ [GPBUInt64FloatDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64FloatDictionary *dict = [GPBUInt64FloatDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:500.f forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const float kValues[] = { 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict2 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ float value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ float value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const float kValues[] = { 500.f, 501.f, 502.f, 503.f };
+ GPBUInt64FloatDictionary *dict =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ float value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:503.f forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+
+ [dict setValue:501.f forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const float kValues2[] = { 502.f, 500.f };
+ GPBUInt64FloatDictionary *dict2 =
+ [[GPBUInt64FloatDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 503.f);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 502.f);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 500.f);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 501.f);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Double
+
+@interface GPBUInt64DoubleDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64DoubleDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64DoubleDictionary *dict = [[GPBUInt64DoubleDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64DoubleDictionary *dict = [GPBUInt64DoubleDictionary dictionaryWithValue:600. forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ double value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 600.);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const double kValues[] = { 600., 601., 602. };
+ GPBUInt64DoubleDictionary *dict =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ double *seenValues = malloc(3 * sizeof(double));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const double kValues1[] = { 600., 601., 602. };
+ const double kValues2[] = { 600., 603., 602. };
+ const double kValues3[] = { 600., 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict1 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64DoubleDictionary *dict1prime =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64DoubleDictionary *dict2 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64DoubleDictionary *dict3 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64DoubleDictionary *dict4 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64DoubleDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64DoubleDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64DoubleDictionary *dict2 =
+ [GPBUInt64DoubleDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64DoubleDictionary *dict = [GPBUInt64DoubleDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:600. forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const double kValues[] = { 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict2 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ double value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ double value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const double kValues[] = { 600., 601., 602., 603. };
+ GPBUInt64DoubleDictionary *dict =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ double value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:603. forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+
+ [dict setValue:601. forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const double kValues2[] = { 602., 600. };
+ GPBUInt64DoubleDictionary *dict2 =
+ [[GPBUInt64DoubleDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 603.);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 602.);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 600.);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 601.);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Enum
+
+@interface GPBUInt64EnumDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64EnumDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64EnumDictionary *dict = [[GPBUInt64EnumDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64EnumDictionary *dict = [GPBUInt64EnumDictionary dictionaryWithValue:700 forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqual(aValue, 700);
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const int32_t kValues[] = { 700, 701, 702 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const int32_t kValues1[] = { 700, 701, 702 };
+ const int32_t kValues2[] = { 700, 703, 702 };
+ const int32_t kValues3[] = { 700, 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict1 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64EnumDictionary *dict1prime =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64EnumDictionary *dict3 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64EnumDictionary *dict4 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64EnumDictionary *dict2 =
+ [GPBUInt64EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64EnumDictionary *dict = [GPBUInt64EnumDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:700 forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 703);
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 701, 702, 703 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:703 forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 703);
+
+ [dict setValue:701 forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 701);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 701);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const int32_t kValues2[] = { 702, 700 };
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 703);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 701);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Enum (Unknown Enums)
+
+@interface GPBUInt64EnumDictionaryUnknownEnumTests : XCTestCase
+@end
+
+@implementation GPBUInt64EnumDictionaryUnknownEnumTests
+
+- (void)testRawBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const int32_t kValues[] = { 700, 801, 702 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL rawValue:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:34ULL rawValue:NULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ int32_t *seenValues = malloc(3 * sizeof(int32_t));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ if (i == 1) {
+ XCTAssertEqual(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+ } else {
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqual(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndRawValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEqualityWithUnknowns {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const int32_t kValues1[] = { 700, 801, 702 }; // Unknown
+ const int32_t kValues2[] = { 700, 803, 702 }; // Unknown
+ const int32_t kValues3[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt64EnumDictionary *dict1 =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64EnumDictionary *dict1prime =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64EnumDictionary *dict3 =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64EnumDictionary *dict4 =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopyWithUnknowns {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknown
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertEqualObjects(dict, dict2);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64EnumDictionary *dict2 =
+ [GPBUInt64EnumDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ [dict release];
+}
+
+- (void)testUnknownAdds {
+ GPBUInt64EnumDictionary *dict =
+ [GPBUInt64EnumDictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertThrowsSpecificNamed([dict setValue:801 forKey:32ULL], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 0U);
+ [dict setRawValue:801 forKey:32ULL]; // Unknown
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 31ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 702, 803 }; // Unknown
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, kGPBUnrecognizedEnumeratorValue);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ [dict2 release];
+}
+
+- (void)testUnknownRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertFalse([dict valueForKey:31ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:32ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:33ULL value:NULL]);
+ XCTAssertFalse([dict valueForKey:34ULL value:NULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutationUnknowns {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 801, 702, 803 }; // Unknowns
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ int32_t value;
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ XCTAssertThrowsSpecificNamed([dict setValue:803 forKey:31ULL], // Unknown
+ NSException, NSInvalidArgumentException);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL value:&value]);
+ XCTAssertEqual(value, 700);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:803 forKey:31ULL]; // Unknown
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+
+ [dict setRawValue:700 forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:33ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 700);
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const int32_t kValues2[] = { 702, 801 }; // Unknown
+ GPBUInt64EnumDictionary *dict2 =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addRawEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:31ULL rawValue:&value]);
+ XCTAssertEqual(value, 803);
+ XCTAssertTrue([dict valueForKey:32ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:32ULL value:&value]);
+ XCTAssertEqual(value, 702);
+ XCTAssertTrue([dict valueForKey:33ULL rawValue:NULL]);
+ XCTAssertTrue([dict valueForKey:33ULL rawValue:&value]);
+ XCTAssertEqual(value, 801);
+ XCTAssertTrue([dict valueForKey:34ULL value:NULL]);
+ XCTAssertTrue([dict valueForKey:34ULL value:&value]);
+ XCTAssertEqual(value, 700);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testCopyUnknowns {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const int32_t kValues[] = { 700, 801, 702, 803 };
+ GPBUInt64EnumDictionary *dict =
+ [[GPBUInt64EnumDictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+ rawValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64EnumDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64EnumDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+#pragma mark - UInt64 -> Object
+
+@interface GPBUInt64ObjectDictionaryTests : XCTestCase
+@end
+
+@implementation GPBUInt64ObjectDictionaryTests
+
+- (void)testEmpty {
+ GPBUInt64ObjectDictionary *dict = [[GPBUInt64ObjectDictionary alloc] init];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:31ULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue, stop)
+ XCTFail(@"Shouldn't get here!");
+ }];
+ [dict release];
+}
+
+- (void)testOne {
+ GPBUInt64ObjectDictionary *dict = [GPBUInt64ObjectDictionary dictionaryWithValue:@"abc" forKey:31ULL];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 1U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertNil([dict valueForKey:32ULL]);
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, id aValue, BOOL *stop) {
+ XCTAssertEqual(aKey, 31ULL);
+ XCTAssertEqualObjects(aValue, @"abc");
+ XCTAssertNotEqual(stop, NULL);
+ }];
+}
+
+- (void)testBasics {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL };
+ const id kValues[] = { @"abc", @"def", @"ghi" };
+ GPBUInt64ObjectDictionary *dict =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertNil([dict valueForKey:34ULL]);
+
+ __block NSUInteger idx = 0;
+ uint64_t *seenKeys = malloc(3 * sizeof(uint64_t));
+ id *seenValues = malloc(3 * sizeof(id));
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, id aValue, BOOL *stop) {
+ XCTAssertLessThan(idx, 3U);
+ seenKeys[idx] = aKey;
+ seenValues[idx] = aValue;
+ XCTAssertNotEqual(stop, NULL);
+ ++idx;
+ }];
+ for (int i = 0; i < 3; ++i) {
+ BOOL foundKey = NO;
+ for (int j = 0; (j < 3) && !foundKey; ++j) {
+ if (kKeys[i] == seenKeys[j]) {
+ foundKey = YES;
+ XCTAssertEqualObjects(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+ }
+ }
+ XCTAssertTrue(foundKey, @"i = %d", i);
+ }
+ free(seenKeys);
+ free(seenValues);
+
+ // Stopping the enumeration.
+ idx = 0;
+ [dict enumerateKeysAndValuesUsingBlock:^(uint64_t aKey, id aValue, BOOL *stop) {
+ #pragma unused(aKey, aValue)
+ if (idx == 1) *stop = YES;
+ XCTAssertNotEqual(idx, 2U);
+ ++idx;
+ }];
+ [dict release];
+}
+
+- (void)testEquality {
+ const uint64_t kKeys1[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const uint64_t kKeys2[] = { 32ULL, 31ULL, 34ULL };
+ const id kValues1[] = { @"abc", @"def", @"ghi" };
+ const id kValues2[] = { @"abc", @"jkl", @"ghi" };
+ const id kValues3[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict1 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1);
+ GPBUInt64ObjectDictionary *dict1prime =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict1prime);
+ GPBUInt64ObjectDictionary *dict2 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ GPBUInt64ObjectDictionary *dict3 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues1
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues1)];
+ XCTAssertNotNil(dict3);
+ GPBUInt64ObjectDictionary *dict4 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues3
+ forKeys:kKeys1
+ count:GPBARRAYSIZE(kValues3)];
+ XCTAssertNotNil(dict4);
+
+ // 1/1Prime should be different objects, but equal.
+ XCTAssertNotEqual(dict1, dict1prime);
+ XCTAssertEqualObjects(dict1, dict1prime);
+ // Equal, so they must have same hash.
+ XCTAssertEqual([dict1 hash], [dict1prime hash]);
+
+ // 2 is save keys, different values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict2);
+
+ // 3 is different keys, samae values; not equal.
+ XCTAssertNotEqualObjects(dict1, dict3);
+
+ // 4 extra pair; not equal
+ XCTAssertNotEqualObjects(dict1, dict4);
+
+ [dict1 release];
+ [dict1prime release];
+ [dict2 release];
+ [dict3 release];
+ [dict4 release];
+}
+
+- (void)testCopy {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64ObjectDictionary *dict2 = [dict copy];
+ XCTAssertNotNil(dict2);
+
+ // Should be new object but equal.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ XCTAssertTrue([dict2 isKindOfClass:[GPBUInt64ObjectDictionary class]]);
+
+ [dict2 release];
+ [dict release];
+}
+
+- (void)testDictionaryFromDictionary {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+
+ GPBUInt64ObjectDictionary *dict2 =
+ [GPBUInt64ObjectDictionary dictionaryWithDictionary:dict];
+ XCTAssertNotNil(dict2);
+
+ // Should be new pointer, but equal objects.
+ XCTAssertNotEqual(dict, dict2);
+ XCTAssertEqualObjects(dict, dict2);
+ [dict release];
+}
+
+- (void)testAdds {
+ GPBUInt64ObjectDictionary *dict = [GPBUInt64ObjectDictionary dictionary];
+ XCTAssertNotNil(dict);
+
+ XCTAssertEqual(dict.count, 0U);
+ [dict setValue:@"abc" forKey:31ULL];
+ XCTAssertEqual(dict.count, 1U);
+
+ const uint64_t kKeys[] = { 32ULL, 33ULL, 34ULL };
+ const id kValues[] = { @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict2 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"jkl");
+ [dict2 release];
+}
+
+- (void)testRemove {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertNil([dict valueForKey:32ULL]);
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"jkl");
+
+ // Remove again does nothing.
+ [dict removeValueForKey:32ULL];
+ XCTAssertEqual(dict.count, 3U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertNil([dict valueForKey:32ULL]);
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"jkl");
+
+ [dict removeValueForKey:34ULL];
+ XCTAssertEqual(dict.count, 2U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertNil([dict valueForKey:32ULL]);
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertNil([dict valueForKey:34ULL]);
+
+ [dict removeAll];
+ XCTAssertEqual(dict.count, 0U);
+ XCTAssertNil([dict valueForKey:31ULL]);
+ XCTAssertNil([dict valueForKey:32ULL]);
+ XCTAssertNil([dict valueForKey:33ULL]);
+ XCTAssertNil([dict valueForKey:34ULL]);
+ [dict release];
+}
+
+- (void)testInplaceMutation {
+ const uint64_t kKeys[] = { 31ULL, 32ULL, 33ULL, 34ULL };
+ const id kValues[] = { @"abc", @"def", @"ghi", @"jkl" };
+ GPBUInt64ObjectDictionary *dict =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues
+ forKeys:kKeys
+ count:GPBARRAYSIZE(kValues)];
+ XCTAssertNotNil(dict);
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"jkl");
+
+ [dict setValue:@"jkl" forKey:31ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"jkl");
+
+ [dict setValue:@"def" forKey:34ULL];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"def");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"def");
+
+ const uint64_t kKeys2[] = { 32ULL, 33ULL };
+ const id kValues2[] = { @"ghi", @"abc" };
+ GPBUInt64ObjectDictionary *dict2 =
+ [[GPBUInt64ObjectDictionary alloc] initWithValues:kValues2
+ forKeys:kKeys2
+ count:GPBARRAYSIZE(kValues2)];
+ XCTAssertNotNil(dict2);
+ [dict addEntriesFromDictionary:dict2];
+ XCTAssertEqual(dict.count, 4U);
+ XCTAssertEqualObjects([dict valueForKey:31ULL], @"jkl");
+ XCTAssertEqualObjects([dict valueForKey:32ULL], @"ghi");
+ XCTAssertEqualObjects([dict valueForKey:33ULL], @"abc");
+ XCTAssertEqualObjects([dict valueForKey:34ULL], @"def");
+
+ [dict2 release];
+ [dict release];
+}
+
+@end
+
+//%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL)
diff --git a/objectivec/Tests/GPBDictionaryTests.pddm b/objectivec/Tests/GPBDictionaryTests.pddm
new file mode 100644
index 00000000..39793e03
--- /dev/null
+++ b/objectivec/Tests/GPBDictionaryTests.pddm
@@ -0,0 +1,1044 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+//%PDDM-DEFINE TEST_FOR_POD_KEY(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4)
+//%TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4)
+//%TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, Object, id, @"abc", @"def", @"ghi", @"jkl")
+
+//%PDDM-DEFINE TESTS_FOR_POD_VALUES(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
+//%TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, UInt32, uint32_t, , 100U, 101U, 102U, 103U)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Int32, int32_t, , 200, 201, 202, 203)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, UInt64, uint64_t, , 300U, 301U, 302U, 303U)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Int64, int64_t, , 400, 401, 402, 403)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Bool, BOOL, , YES, YES, NO, NO)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Float, float, , 500.f, 501.f, 502.f, 503.f)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Double, double, , 600., 601., 602., 603.)
+//%TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, Raw, 700, 701, 702, 703)
+//%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
+
+//%PDDM-DEFINE TESTS_FOR_POD_VALUE(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
+//%TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, , POD, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
+
+//%PDDM-DEFINE TESTS_FOR_POD_KEY_OBJECT_VALUE(KEY_NAME, KEY_TYPE, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VAL1, VAL2, VAL3, VAL4)
+//%TESTS_COMMON(KEY_NAME, KEY_TYPE, , , KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, Objects, OBJECT, , VAL1, VAL2, VAL3, VAL4)
+
+//%PDDM-DEFINE TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VSUFFIX, VHELPER, VACCESSOR, VAL1, VAL2, VAL3, VAL4)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
+//%
+//%- (void)testEmpty {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% #pragma unused(aKey, aValue, stop)
+//% XCTFail(@"Shouldn't get here!");
+//% }];
+//% [dict release];
+//%}
+//%
+//%- (void)testOne {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValue:VAL1 forKey:KEY1];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 1U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertEqual##KSUFFIX(aKey, KEY1);
+//% XCTAssertEqual##VSUFFIX(aValue, VAL1);
+//% XCTAssertNotEqual(stop, NULL);
+//% }];
+//%}
+//%
+//%- (void)testBasics {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 3U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//% __block NSUInteger idx = 0;
+//% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
+//% VALUE_TYPE *seenValues = malloc(3 * sizeof(VALUE_TYPE));
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertLessThan(idx, 3U);
+//% seenKeys[idx] = aKey;
+//% seenValues[idx] = aValue;
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx;
+//% }];
+//% for (int i = 0; i < 3; ++i) {
+//% BOOL foundKey = NO;
+//% for (int j = 0; (j < 3) && !foundKey; ++j) {
+//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//% foundKey = YES;
+//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+//% }
+//% }
+//% XCTAssertTrue(foundKey, @"i = %d", i);
+//% }
+//% free(seenKeys);
+//% free(seenValues);
+//%
+//% // Stopping the enumeration.
+//% idx = 0;
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% #pragma unused(aKey, aValue)
+//% if (idx == 1) *stop = YES;
+//% XCTAssertNotEqual(idx, 2U);
+//% ++idx;
+//% }];
+//% [dict release];
+//%}
+//%
+//%- (void)testEquality {
+//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
+//% const VALUE_TYPE kValues1[] = { VAL1, VAL2, VAL3 };
+//% const VALUE_TYPE kValues2[] = { VAL1, VAL4, VAL3 };
+//% const VALUE_TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1prime);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict3);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues3
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues3)];
+//% XCTAssertNotNil(dict4);
+//%
+//% // 1/1Prime should be different objects, but equal.
+//% XCTAssertNotEqual(dict1, dict1prime);
+//% XCTAssertEqualObjects(dict1, dict1prime);
+//% // Equal, so they must have same hash.
+//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
+//%
+//% // 2 is save keys, different values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict2);
+//%
+//% // 3 is different keys, samae values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict3);
+//%
+//% // 4 extra pair; not equal
+//% XCTAssertNotEqualObjects(dict1, dict4);
+//%
+//% [dict1 release];
+//% [dict1prime release];
+//% [dict2 release];
+//% [dict3 release];
+//% [dict4 release];
+//%}
+//%
+//%- (void)testCopy {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new object but equal.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%- (void)testDictionaryFromDictionary {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% [dict release];
+//%}
+//%
+//%- (void)testAdds {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
+//% XCTAssertNotNil(dict);
+//%
+//% XCTAssertEqual(dict.count, 0U);
+//% [dict setValue:VAL1 forKey:KEY1];
+//% XCTAssertEqual(dict.count, 1U);
+//%
+//% const KEY_TYPE KisP##kKeys[] = { KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict2);
+//% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 4U);
+//%
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//% [dict2 release];
+//%}
+//%
+//%- (void)testRemove {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 4U);
+//%
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 3U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% // Remove again does nothing.
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 3U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict removeValueForKey:KEY4];
+//% XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//% [dict removeAll];
+//% XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//% [dict release];
+//%}
+//%
+//%- (void)testInplaceMutation {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 4U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict setValue:VAL4 forKey:KEY1];
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict setValue:VAL2 forKey:KEY4];
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL2)
+//%
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
+//% const VALUE_TYPE kValues2[] = { VAL3, VAL1 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% [dict add##VACCESSOR##EntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL2)
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%@end
+//%
+
+//%PDDM-DEFINE TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4)
+//%TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS2(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, Enum, int32_t, , POD, 700, 801, 702, 803)
+//%PDDM-DEFINE TESTS_FOR_ENUM_VALUE_RAW_ADDITIONS2(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, KEY3, KEY4, VALUE_NAME, VALUE_TYPE, VSUFFIX, VHELPER, VAL1, VAL2, VAL3, VAL4)
+//%#pragma mark - KEY_NAME -> VALUE_NAME (Unknown Enums)
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryUnknownEnumTests
+//%
+//%- (void)testRawBasics {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 3U);
+//% XCTAssertTrue(dict.validationFunc == TestingEnum_IsValidValue); // Pointer comparison
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%RAW_VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//% __block NSUInteger idx = 0;
+//% KEY_TYPE KisP##*seenKeys = malloc(3 * sizeof(KEY_TYPE##KisP));
+//% VALUE_TYPE *seenValues = malloc(3 * sizeof(VALUE_TYPE));
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertLessThan(idx, 3U);
+//% seenKeys[idx] = aKey;
+//% seenValues[idx] = aValue;
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx;
+//% }];
+//% for (int i = 0; i < 3; ++i) {
+//% BOOL foundKey = NO;
+//% for (int j = 0; (j < 3) && !foundKey; ++j) {
+//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//% foundKey = YES;
+//% if (i == 1) {
+//% XCTAssertEqual##VSUFFIX(kGPBUnrecognizedEnumeratorValue, seenValues[j], @"i = %d, j = %d", i, j);
+//% } else {
+//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+//% }
+//% }
+//% }
+//% XCTAssertTrue(foundKey, @"i = %d", i);
+//% }
+//% idx = 0;
+//% [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertLessThan(idx, 3U);
+//% seenKeys[idx] = aKey;
+//% seenValues[idx] = aValue;
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx;
+//% }];
+//% for (int i = 0; i < 3; ++i) {
+//% BOOL foundKey = NO;
+//% for (int j = 0; (j < 3) && !foundKey; ++j) {
+//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//% foundKey = YES;
+//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+//% }
+//% }
+//% XCTAssertTrue(foundKey, @"i = %d", i);
+//% }
+//% free(seenKeys);
+//% free(seenValues);
+//%
+//% // Stopping the enumeration.
+//% idx = 0;
+//% [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% #pragma unused(aKey, aValue)
+//% if (idx == 1) *stop = YES;
+//% XCTAssertNotEqual(idx, 2U);
+//% ++idx;
+//% }];
+//% [dict release];
+//%}
+//%
+//%- (void)testEqualityWithUnknowns {
+//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1, KEY4 };
+//% const VALUE_TYPE kValues1[] = { VAL1, VAL2, VAL3 }; // Unknown
+//% const VALUE_TYPE kValues2[] = { VAL1, VAL4, VAL3 }; // Unknown
+//% const VALUE_TYPE kValues3[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1prime);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict3);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues3
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues3)];
+//% XCTAssertNotNil(dict4);
+//%
+//% // 1/1Prime should be different objects, but equal.
+//% XCTAssertNotEqual(dict1, dict1prime);
+//% XCTAssertEqualObjects(dict1, dict1prime);
+//% // Equal, so they must have same hash.
+//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
+//%
+//% // 2 is save keys, different values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict2);
+//%
+//% // 3 is different keys, samae values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict3);
+//%
+//% // 4 extra pair; not equal
+//% XCTAssertNotEqualObjects(dict1, dict4);
+//%
+//% [dict1 release];
+//% [dict1prime release];
+//% [dict2 release];
+//% [dict3 release];
+//% [dict4 release];
+//%}
+//%
+//%- (void)testCopyWithUnknowns {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknown
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+//% XCTAssertEqualObjects(dict, dict2);
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%- (void)testDictionaryFromDictionary {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+//% [dict release];
+//%}
+//%
+//%- (void)testUnknownAdds {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValidationFunction:TestingEnum_IsValidValue];
+//% XCTAssertNotNil(dict);
+//%
+//% XCTAssertEqual(dict.count, 0U);
+//% XCTAssertThrowsSpecificNamed([dict setValue:VAL2 forKey:KEY2], // Unknown
+//% NSException, NSInvalidArgumentException);
+//% XCTAssertEqual(dict.count, 0U);
+//% [dict setRawValue:VAL2 forKey:KEY2]; // Unknown
+//% XCTAssertEqual(dict.count, 1U);
+//%
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL3, VAL4 }; // Unknown
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict2);
+//% [dict addRawEntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 4U);
+//%
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, kGPBUnrecognizedEnumeratorValue)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, kGPBUnrecognizedEnumeratorValue)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//% [dict2 release];
+//%}
+//%
+//%- (void)testUnknownRemove {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 4U);
+//%
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 3U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% // Remove again does nothing.
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 3U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict removeValueForKey:KEY4];
+//% XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//%
+//% [dict removeAll];
+//% XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY3)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY4)
+//% [dict release];
+//%}
+//%
+//%- (void)testInplaceMutationUnknowns {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 }; // Unknowns
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 4U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% XCTAssertThrowsSpecificNamed([dict setValue:VAL4 forKey:KEY1], // Unknown
+//% NSException, NSInvalidArgumentException);
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict setRawValue:VAL4 forKey:KEY1]; // Unknown
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY4, VAL4)
+//%
+//% [dict setRawValue:VAL1 forKey:KEY4];
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY3, VAL3)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL1)
+//%
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY3 };
+//% const VALUE_TYPE kValues2[] = { VAL3, VAL2 }; // Unknown
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% [dict addRawEntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 4U);
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY1, VAL4)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL3)
+//%TEST_RAW_VALUE##VHELPER(dict, value, KEY3, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY4, VAL1)
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%- (void)testCopyUnknowns {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2, KEY3, KEY4 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2, VAL3, VAL4 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S VALUE_NAME$S rawValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% XCTAssertEqual(dict.validationFunc, dict2.validationFunc); // Pointer comparison
+//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%@end
+//%
+
+//
+// Helpers for PODs
+//
+
+//%PDDM-DEFINE DECLARE_VALUE_STORAGEPOD(VALUE_TYPE, NAME)
+//% VALUE_TYPE NAME;
+//%
+//%PDDM-DEFINE VALUE_NOT_FOUNDPOD(DICT, KEY)
+//% XCTAssertFalse([DICT valueForKey:KEY value:NULL]);
+//%PDDM-DEFINE TEST_VALUEPOD(DICT, STORAGE, KEY, VALUE)
+//% XCTAssertTrue([DICT valueForKey:KEY value:NULL]);
+//% XCTAssertTrue([DICT valueForKey:KEY value:&STORAGE]);
+//% XCTAssertEqual(STORAGE, VALUE);
+//%PDDM-DEFINE COMPARE_KEYS(KEY1, KEY2)
+//%KEY1 == KEY2
+//%PDDM-DEFINE RAW_VALUE_NOT_FOUNDPOD(DICT, KEY)
+//% XCTAssertFalse([DICT valueForKey:KEY rawValue:NULL]);
+//%PDDM-DEFINE TEST_RAW_VALUEPOD(DICT, STORAGE, KEY, VALUE)
+//% XCTAssertTrue([DICT valueForKey:KEY rawValue:NULL]);
+//% XCTAssertTrue([DICT valueForKey:KEY rawValue:&STORAGE]);
+//% XCTAssertEqual(STORAGE, VALUE);
+
+//
+// Helpers for Objects
+//
+
+//%PDDM-DEFINE DECLARE_VALUE_STORAGEOBJECT(VALUE_TYPE, NAME)
+// Empty
+//%PDDM-DEFINE VALUE_NOT_FOUNDOBJECT(DICT, KEY)
+//% XCTAssertNil([DICT valueForKey:KEY]);
+//%PDDM-DEFINE TEST_VALUEOBJECT(DICT, STORAGE, KEY, VALUE)
+//% XCTAssertEqualObjects([DICT valueForKey:KEY], VALUE);
+//%PDDM-DEFINE COMPARE_KEYSObjects(KEY1, KEY2)
+//%[KEY1 isEqual:KEY2]
+
+//
+// Helpers for tests.
+//
+
+//%PDDM-DEFINE TEST_HELPERS(KEY_NAME, KEY_TYPE, KisP)
+//%#ifndef GPBARRAYSIZE
+//%#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+//%#endif // GPBARRAYSIZE
+//%
+//%// To let the testing macros work, add some extra methods to simplify things.
+//%@interface GPB##KEY_NAME##EnumDictionary (TestingTweak)
+//%+ (instancetype)dictionaryWithValue:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key;
+//%- (instancetype)initWithValues:(const int32_t [])values
+//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//% count:(NSUInteger)count;
+//%@end
+//%
+//%static BOOL TestingEnum_IsValidValue(int32_t value) {
+//% switch (value) {
+//% case 700:
+//% case 701:
+//% case 702:
+//% case 703:
+//% return YES;
+//% default:
+//% return NO;
+//% }
+//%}
+//%
+//%@implementation GPB##KEY_NAME##EnumDictionary (TestingTweak)
+//%+ (instancetype)dictionaryWithValue:(int32_t)value forKey:(KEY_TYPE##KisP$S##KisP)key {
+//% // Cast is needed to compiler knows what class we are invoking initWithValues: on to get the
+//% // type correct.
+//% return [[(GPB##KEY_NAME##EnumDictionary*)[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
+//% KEY_NAME$S rawValues:&value
+//% KEY_NAME$S forKeys:&key
+//% KEY_NAME$S count:1] autorelease];
+//%}
+//%- (instancetype)initWithValues:(const int32_t [])values
+//% forKeys:(const KEY_TYPE##KisP$S##KisP [])keys
+//% count:(NSUInteger)count {
+//% return [self initWithValidationFunction:TestingEnum_IsValidValue
+//% rawValues:values
+//% forKeys:keys
+//% count:count];
+//%}
+//%@end
+//%
+//%
+
+
+//
+// BOOL test macros
+//
+//TODO(thomasvl): enum tests
+
+//%PDDM-DEFINE BOOL_TESTS_FOR_POD_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
+//%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, , POD, VAL1, VAL2)
+
+//%PDDM-DEFINE TESTS_FOR_BOOL_KEY_OBJECT_VALUE(VALUE_NAME, VALUE_TYPE, VAL1, VAL2)
+//%BOOL_TESTS_COMMON(Bool, BOOL, , , YES, NO, VALUE_NAME, VALUE_TYPE, Objects, OBJECT, VAL1, VAL2)
+
+//%PDDM-DEFINE BOOL_TESTS_COMMON(KEY_NAME, KEY_TYPE, KisP, KSUFFIX, KEY1, KEY2, VALUE_NAME, VALUE_TYPE, VSUFFIX, VHELPER, VAL1, VAL2)
+//%#pragma mark - KEY_NAME -> VALUE_NAME
+//%
+//%@interface GPB##KEY_NAME##VALUE_NAME##DictionaryTests : XCTestCase
+//%@end
+//%
+//%@implementation GPB##KEY_NAME##VALUE_NAME##DictionaryTests
+//%
+//%- (void)testEmpty {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] init];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% #pragma unused(aKey, aValue, stop)
+//% XCTFail(@"Shouldn't get here!");
+//% }];
+//% [dict release];
+//%}
+//%
+//%- (void)testOne {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithValue:VAL1 forKey:KEY1];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 1U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertEqual##KSUFFIX(aKey, KEY1);
+//% XCTAssertEqual##VSUFFIX(aValue, VAL1);
+//% XCTAssertNotEqual(stop, NULL);
+//% }];
+//%}
+//%
+//%- (void)testBasics {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 2U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%
+//% __block NSUInteger idx = 0;
+//% KEY_TYPE KisP##*seenKeys = malloc(2 * sizeof(KEY_TYPE##KisP));
+//% VALUE_TYPE *seenValues = malloc(2 * sizeof(VALUE_TYPE));
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% XCTAssertLessThan(idx, 2U);
+//% seenKeys[idx] = aKey;
+//% seenValues[idx] = aValue;
+//% XCTAssertNotEqual(stop, NULL);
+//% ++idx;
+//% }];
+//% for (int i = 0; i < 2; ++i) {
+//% BOOL foundKey = NO;
+//% for (int j = 0; (j < 2) && !foundKey; ++j) {
+//% if (COMPARE_KEYS##KSUFFIX(kKeys[i], seenKeys[j])) {
+//% foundKey = YES;
+//% XCTAssertEqual##VSUFFIX(kValues[i], seenValues[j], @"i = %d, j = %d", i, j);
+//% }
+//% }
+//% XCTAssertTrue(foundKey, @"i = %d", i);
+//% }
+//% free(seenKeys);
+//% free(seenValues);
+//%
+//% // Stopping the enumeration.
+//% idx = 0;
+//% [dict enumerateKeysAndValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
+//% #pragma unused(aKey, aValue)
+//% if (idx == 0) *stop = YES;
+//% XCTAssertNotEqual(idx, 2U);
+//% ++idx;
+//% }];
+//% [dict release];
+//%}
+//%
+//%- (void)testEquality {
+//% const KEY_TYPE KisP##kKeys1[] = { KEY1, KEY2 };
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
+//% const VALUE_TYPE kValues1[] = { VAL1, VAL2 };
+//% const VALUE_TYPE kValues2[] = { VAL2, VAL1 };
+//% const VALUE_TYPE kValues3[] = { VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict1prime =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict1prime);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict3 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues1
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues1)];
+//% XCTAssertNotNil(dict3);
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict4 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues3
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys1
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues3)];
+//% XCTAssertNotNil(dict4);
+//%
+//% // 1/1Prime should be different objects, but equal.
+//% XCTAssertNotEqual(dict1, dict1prime);
+//% XCTAssertEqualObjects(dict1, dict1prime);
+//% // Equal, so they must have same hash.
+//% XCTAssertEqual([dict1 hash], [dict1prime hash]);
+//%
+//% // 2 is save keys, different values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict2);
+//%
+//% // 3 is different keys, samae values; not equal.
+//% XCTAssertNotEqualObjects(dict1, dict3);
+//%
+//% // 4 Fewer pairs; not equal
+//% XCTAssertNotEqualObjects(dict1, dict4);
+//%
+//% [dict1 release];
+//% [dict1prime release];
+//% [dict2 release];
+//% [dict3 release];
+//% [dict4 release];
+//%}
+//%
+//%- (void)testCopy {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 = [dict copy];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new object but equal.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% XCTAssertTrue([dict2 isKindOfClass:[GPB##KEY_NAME##VALUE_NAME##Dictionary class]]);
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%- (void)testDictionaryFromDictionary {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//%
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionaryWithDictionary:dict];
+//% XCTAssertNotNil(dict2);
+//%
+//% // Should be new pointer, but equal objects.
+//% XCTAssertNotEqual(dict, dict2);
+//% XCTAssertEqualObjects(dict, dict2);
+//% [dict release];
+//%}
+//%
+//%- (void)testAdds {
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict = [GPB##KEY_NAME##VALUE_NAME##Dictionary dictionary];
+//% XCTAssertNotNil(dict);
+//%
+//% XCTAssertEqual(dict.count, 0U);
+//% [dict setValue:VAL1 forKey:KEY1];
+//% XCTAssertEqual(dict.count, 1U);
+//%
+//% const KEY_TYPE KisP##kKeys[] = { KEY2 };
+//% const VALUE_TYPE kValues[] = { VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict2);
+//% [dict addEntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 2U);
+//%
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//% [dict2 release];
+//%}
+//%
+//%- (void)testRemove {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2};
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 2U);
+//%
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 1U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%
+//% // Remove again does nothing.
+//% [dict removeValueForKey:KEY2];
+//% XCTAssertEqual(dict.count, 1U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//%
+//% [dict removeAll];
+//% XCTAssertEqual(dict.count, 0U);
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY1)
+//%VALUE_NOT_FOUND##VHELPER(dict, KEY2)
+//% [dict release];
+//%}
+//%
+//%- (void)testInplaceMutation {
+//% const KEY_TYPE KisP##kKeys[] = { KEY1, KEY2 };
+//% const VALUE_TYPE kValues[] = { VAL1, VAL2 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues)];
+//% XCTAssertNotNil(dict);
+//% XCTAssertEqual(dict.count, 2U);
+//%DECLARE_VALUE_STORAGE##VHELPER(VALUE_TYPE, value)TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%
+//% [dict setValue:VAL2 forKey:KEY1];
+//% XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%
+//% [dict setValue:VAL1 forKey:KEY2];
+//% XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL2)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL1)
+//%
+//% const KEY_TYPE KisP##kKeys2[] = { KEY2, KEY1 };
+//% const VALUE_TYPE kValues2[] = { VAL2, VAL1 };
+//% GPB##KEY_NAME##VALUE_NAME##Dictionary *dict2 =
+//% [[GPB##KEY_NAME##VALUE_NAME##Dictionary alloc] initWithValues:kValues2
+//% KEY_NAME$S VALUE_NAME$S forKeys:kKeys2
+//% KEY_NAME$S VALUE_NAME$S count:GPBARRAYSIZE(kValues2)];
+//% XCTAssertNotNil(dict2);
+//% [dict addEntriesFromDictionary:dict2];
+//% XCTAssertEqual(dict.count, 2U);
+//%TEST_VALUE##VHELPER(dict, value, KEY1, VAL1)
+//%TEST_VALUE##VHELPER(dict, value, KEY2, VAL2)
+//%
+//% [dict2 release];
+//% [dict release];
+//%}
+//%
+//%@end
+//%
+
diff --git a/objectivec/Tests/GPBFilteredMessageTests.m b/objectivec/Tests/GPBFilteredMessageTests.m
new file mode 100644
index 00000000..b0588837
--- /dev/null
+++ b/objectivec/Tests/GPBFilteredMessageTests.m
@@ -0,0 +1,98 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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.
+
+// Tests our filter system for ObjC.
+// The proto being filtered is unittest_filter.proto.
+// The filter file is Filter.txt.
+
+#import "GPBTestUtilities.h"
+
+#import "google/protobuf/UnittestFilter.pbobjc.h"
+
+// If we get an error about this already being defined, it is most likely
+// because of an error in protoc which is supposed to be filtering
+// the Remove message.
+enum { Other_FieldNumber_B = 0 };
+
+@interface FilteredMessageTests : GPBTestCase
+@end
+
+@implementation FilteredMessageTests
+
+- (void)testEnumFiltering {
+ // If compile fails here it is because protoc did not generate KeepEnum.
+ XCTAssertTrue(KeepEnum_IsValidValue(KeepEnum_KeepValue));
+ XCTAssertNotNil(KeepEnum_EnumDescriptor());
+
+ // If compile fails here it is because protoc did not generate
+ // KeepEnumInsideEnum and is probably due to nested enum handling being
+ // broken.
+ XCTAssertTrue(RemoveEnumMessage_KeepEnumInside_IsValidValue(
+ RemoveEnumMessage_KeepEnumInside_KeepValue));
+ XCTAssertNotNil(RemoveEnumMessage_KeepEnumInside_EnumDescriptor());
+}
+
+- (void)testMessageFiltering {
+ // Messages that should be generated.
+ XCTAssertNil([UnittestFilterRoot extensionRegistry]);
+ XCTAssertNotNil([[[Keep alloc] init] autorelease]);
+ XCTAssertNotNil([[[Other alloc] init] autorelease]);
+ XCTAssertNotNil([[[RemoveJustKidding alloc] init] autorelease]);
+ XCTAssertNotNil(
+ [[[RemoveEnumMessage_KeepNestedInside alloc] init] autorelease]);
+
+ // Messages that should not be generated
+ XCTAssertNil(NSClassFromString(@"Remove"));
+ XCTAssertNil(NSClassFromString(@"RemoveEnumMessage"));
+ XCTAssertNil(NSClassFromString(@"RemoveEnumMessage_RemoveNestedInside"));
+
+ // These should all fail compile if protoc is bad.
+ XCTAssertTrue([Other instancesRespondToSelector:@selector(hasA)]);
+ XCTAssertTrue([Other instancesRespondToSelector:@selector(setHasA:)]);
+ XCTAssertTrue([Other instancesRespondToSelector:@selector(a)]);
+ XCTAssertTrue([Other instancesRespondToSelector:@selector(setA:)]);
+
+ // These the compiler should not generate.
+ XCTAssertFalse(
+ [Other instancesRespondToSelector:NSSelectorFromString(@"hasB")]);
+ XCTAssertFalse(
+ [Other instancesRespondToSelector:NSSelectorFromString(@"setHasB:")]);
+ XCTAssertFalse([Other instancesRespondToSelector:NSSelectorFromString(@"b")]);
+ XCTAssertFalse(
+ [Other instancesRespondToSelector:NSSelectorFromString(@"setB:")]);
+
+ // This should fail if protoc filters it.
+ XCTAssertEqual(Other_FieldNumber_A, 1);
+
+ // Make sure the definition at the top of the file is providing the value.
+ XCTAssertEqual(Other_FieldNumber_B, 0);
+}
+
+@end
diff --git a/objectivec/Tests/GPBMessageTests+Merge.m b/objectivec/Tests/GPBMessageTests+Merge.m
new file mode 100644
index 00000000..599ad055
--- /dev/null
+++ b/objectivec/Tests/GPBMessageTests+Merge.m
@@ -0,0 +1,700 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+
+@interface MessageMergeTests : GPBTestCase
+@end
+
+@implementation MessageMergeTests
+
+// TODO(thomasvl): Pull tests over from GPBMessageTests that are merge specific.
+
+- (void)testProto3MergingAndZeroValues {
+ // Proto2 covered in other tests.
+
+ Message3 *src = [[Message3 alloc] init];
+ Message3 *dst = [[Message3 alloc] init];
+ NSData *testData1 = [@"abc" dataUsingEncoding:NSUTF8StringEncoding];
+ NSData *testData2 = [@"def" dataUsingEncoding:NSUTF8StringEncoding];
+
+ dst.optionalInt32 = 1;
+ dst.optionalInt64 = 1;
+ dst.optionalUint32 = 1;
+ dst.optionalUint64 = 1;
+ dst.optionalSint32 = 1;
+ dst.optionalSint64 = 1;
+ dst.optionalFixed32 = 1;
+ dst.optionalFixed64 = 1;
+ dst.optionalSfixed32 = 1;
+ dst.optionalSfixed64 = 1;
+ dst.optionalFloat = 1.0f;
+ dst.optionalDouble = 1.0;
+ dst.optionalBool = YES;
+ dst.optionalString = @"bar";
+ dst.optionalBytes = testData1;
+ dst.optionalEnum = Message3_Enum_Bar;
+
+ // All zeros, nothing should overright.
+
+ src.optionalInt32 = 0;
+ src.optionalInt64 = 0;
+ src.optionalUint32 = 0;
+ src.optionalUint64 = 0;
+ src.optionalSint32 = 0;
+ src.optionalSint64 = 0;
+ src.optionalFixed32 = 0;
+ src.optionalFixed64 = 0;
+ src.optionalSfixed32 = 0;
+ src.optionalSfixed64 = 0;
+ src.optionalFloat = 0.0f;
+ src.optionalDouble = 0.0;
+ src.optionalBool = NO;
+ src.optionalString = @"";
+ src.optionalBytes = [NSData data];
+ src.optionalEnum = Message3_Enum_Foo; // first value
+
+ [dst mergeFrom:src];
+
+ XCTAssertEqual(dst.optionalInt32, 1);
+ XCTAssertEqual(dst.optionalInt64, 1);
+ XCTAssertEqual(dst.optionalUint32, 1U);
+ XCTAssertEqual(dst.optionalUint64, 1U);
+ XCTAssertEqual(dst.optionalSint32, 1);
+ XCTAssertEqual(dst.optionalSint64, 1);
+ XCTAssertEqual(dst.optionalFixed32, 1U);
+ XCTAssertEqual(dst.optionalFixed64, 1U);
+ XCTAssertEqual(dst.optionalSfixed32, 1);
+ XCTAssertEqual(dst.optionalSfixed64, 1);
+ XCTAssertEqual(dst.optionalFloat, 1.0f);
+ XCTAssertEqual(dst.optionalDouble, 1.0);
+ XCTAssertEqual(dst.optionalBool, YES);
+ XCTAssertEqualObjects(dst.optionalString, @"bar");
+ XCTAssertEqualObjects(dst.optionalBytes, testData1);
+ XCTAssertEqual(dst.optionalEnum, Message3_Enum_Bar);
+
+ // Half the values that will replace.
+
+ src.optionalInt32 = 0;
+ src.optionalInt64 = 2;
+ src.optionalUint32 = 0;
+ src.optionalUint64 = 2;
+ src.optionalSint32 = 0;
+ src.optionalSint64 = 2;
+ src.optionalFixed32 = 0;
+ src.optionalFixed64 = 2;
+ src.optionalSfixed32 = 0;
+ src.optionalSfixed64 = 2;
+ src.optionalFloat = 0.0f;
+ src.optionalDouble = 2.0;
+ src.optionalBool = YES; // No other value to use. :(
+ src.optionalString = @"baz";
+ src.optionalBytes = nil;
+ src.optionalEnum = Message3_Enum_Baz;
+
+ [dst mergeFrom:src];
+
+ XCTAssertEqual(dst.optionalInt32, 1);
+ XCTAssertEqual(dst.optionalInt64, 2);
+ XCTAssertEqual(dst.optionalUint32, 1U);
+ XCTAssertEqual(dst.optionalUint64, 2U);
+ XCTAssertEqual(dst.optionalSint32, 1);
+ XCTAssertEqual(dst.optionalSint64, 2);
+ XCTAssertEqual(dst.optionalFixed32, 1U);
+ XCTAssertEqual(dst.optionalFixed64, 2U);
+ XCTAssertEqual(dst.optionalSfixed32, 1);
+ XCTAssertEqual(dst.optionalSfixed64, 2);
+ XCTAssertEqual(dst.optionalFloat, 1.0f);
+ XCTAssertEqual(dst.optionalDouble, 2.0);
+ XCTAssertEqual(dst.optionalBool, YES);
+ XCTAssertEqualObjects(dst.optionalString, @"baz");
+ XCTAssertEqualObjects(dst.optionalBytes, testData1);
+ XCTAssertEqual(dst.optionalEnum, Message3_Enum_Baz);
+
+ // Other half the values that will replace.
+
+ src.optionalInt32 = 3;
+ src.optionalInt64 = 0;
+ src.optionalUint32 = 3;
+ src.optionalUint64 = 0;
+ src.optionalSint32 = 3;
+ src.optionalSint64 = 0;
+ src.optionalFixed32 = 3;
+ src.optionalFixed64 = 0;
+ src.optionalSfixed32 = 3;
+ src.optionalSfixed64 = 0;
+ src.optionalFloat = 3.0f;
+ src.optionalDouble = 0.0;
+ src.optionalBool = YES; // No other value to use. :(
+ src.optionalString = nil;
+ src.optionalBytes = testData2;
+ src.optionalEnum = Message3_Enum_Foo;
+
+ [dst mergeFrom:src];
+
+ XCTAssertEqual(dst.optionalInt32, 3);
+ XCTAssertEqual(dst.optionalInt64, 2);
+ XCTAssertEqual(dst.optionalUint32, 3U);
+ XCTAssertEqual(dst.optionalUint64, 2U);
+ XCTAssertEqual(dst.optionalSint32, 3);
+ XCTAssertEqual(dst.optionalSint64, 2);
+ XCTAssertEqual(dst.optionalFixed32, 3U);
+ XCTAssertEqual(dst.optionalFixed64, 2U);
+ XCTAssertEqual(dst.optionalSfixed32, 3);
+ XCTAssertEqual(dst.optionalSfixed64, 2);
+ XCTAssertEqual(dst.optionalFloat, 3.0f);
+ XCTAssertEqual(dst.optionalDouble, 2.0);
+ XCTAssertEqual(dst.optionalBool, YES);
+ XCTAssertEqualObjects(dst.optionalString, @"baz");
+ XCTAssertEqualObjects(dst.optionalBytes, testData2);
+ XCTAssertEqual(dst.optionalEnum, Message3_Enum_Baz);
+
+ [src release];
+ [dst release];
+}
+
+- (void)testProto3MergingEnums {
+ UnknownEnumsMyMessage *src = [UnknownEnumsMyMessage message];
+ UnknownEnumsMyMessage *dst = [UnknownEnumsMyMessage message];
+
+ // Known value.
+
+ src.e = UnknownEnumsMyEnum_Bar;
+ src.repeatedEArray =
+ [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+ rawValue:UnknownEnumsMyEnum_Bar];
+ src.repeatedPackedEArray =
+ [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+ rawValue:UnknownEnumsMyEnum_Bar];
+ src.oneofE1 = UnknownEnumsMyEnum_Bar;
+
+ [dst mergeFrom:src];
+
+ XCTAssertEqual(dst.e, UnknownEnumsMyEnum_Bar);
+ XCTAssertEqual(dst.repeatedEArray.count, 1U);
+ XCTAssertEqual([dst.repeatedEArray valueAtIndex:0], UnknownEnumsMyEnum_Bar);
+ XCTAssertEqual(dst.repeatedPackedEArray.count, 1U);
+ XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:0],
+ UnknownEnumsMyEnum_Bar);
+ XCTAssertEqual(dst.oneofE1, UnknownEnumsMyEnum_Bar);
+
+ // Unknown value.
+
+ const int32_t kUnknownValue = 666;
+
+ SetUnknownEnumsMyMessage_E_RawValue(src, kUnknownValue);
+ src.repeatedEArray =
+ [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+ rawValue:kUnknownValue];
+ src.repeatedPackedEArray =
+ [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+ rawValue:kUnknownValue];
+ SetUnknownEnumsMyMessage_OneofE1_RawValue(src, kUnknownValue);
+
+ [dst mergeFrom:src];
+
+ XCTAssertEqual(dst.e, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(UnknownEnumsMyMessage_E_RawValue(dst), kUnknownValue);
+ XCTAssertEqual(dst.repeatedEArray.count, 2U);
+ XCTAssertEqual([dst.repeatedEArray valueAtIndex:0], UnknownEnumsMyEnum_Bar);
+ XCTAssertEqual([dst.repeatedEArray valueAtIndex:1],
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([dst.repeatedEArray rawValueAtIndex:1], kUnknownValue);
+ XCTAssertEqual(dst.repeatedPackedEArray.count, 2U);
+ XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:0],
+ UnknownEnumsMyEnum_Bar);
+ XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:1],
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([dst.repeatedPackedEArray rawValueAtIndex:1], kUnknownValue);
+ XCTAssertEqual(dst.oneofE1,
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(UnknownEnumsMyMessage_OneofE1_RawValue(dst), kUnknownValue);
+}
+
+- (void)testProto2MergeOneof {
+ Message2 *src = [Message2 message];
+ Message2 *dst = [Message2 message];
+
+ //
+ // Make sure whatever is in dst gets cleared out be merging in something else.
+ //
+
+ dst.oneofEnum = Message2_Enum_Bar;
+
+//%PDDM-DEFINE MERGE2_TEST(SET_NAME, SET_VALUE, CLEARED_NAME, CLEARED_DEFAULT)
+//% src.oneof##SET_NAME = SET_VALUE;
+//% [dst mergeFrom:src];
+//% XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_Oneof##SET_NAME);
+//% XCTAssertEqual(dst.oneof##SET_NAME, SET_VALUE);
+//% XCTAssertEqual(dst.oneof##CLEARED_NAME, CLEARED_DEFAULT);
+//%
+//%PDDM-EXPAND MERGE2_TEST(Int32, 10, Enum, Message2_Enum_Baz)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofInt32 = 10;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(dst.oneofInt32, 10);
+ XCTAssertEqual(dst.oneofEnum, Message2_Enum_Baz);
+
+//%PDDM-EXPAND MERGE2_TEST(Int64, 11, Int32, 100)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofInt64 = 11;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(dst.oneofInt64, 11);
+ XCTAssertEqual(dst.oneofInt32, 100);
+
+//%PDDM-EXPAND MERGE2_TEST(Uint32, 12U, Int64, 101)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofUint32 = 12U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(dst.oneofUint32, 12U);
+ XCTAssertEqual(dst.oneofInt64, 101);
+
+//%PDDM-EXPAND MERGE2_TEST(Uint64, 13U, Uint32, 102U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofUint64 = 13U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(dst.oneofUint64, 13U);
+ XCTAssertEqual(dst.oneofUint32, 102U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sint32, 14, Uint64, 103U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSint32 = 14;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(dst.oneofSint32, 14);
+ XCTAssertEqual(dst.oneofUint64, 103U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sint64, 15, Sint32, 104)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSint64 = 15;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(dst.oneofSint64, 15);
+ XCTAssertEqual(dst.oneofSint32, 104);
+
+//%PDDM-EXPAND MERGE2_TEST(Fixed32, 16U, Sint64, 105)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFixed32 = 16U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(dst.oneofFixed32, 16U);
+ XCTAssertEqual(dst.oneofSint64, 105);
+
+//%PDDM-EXPAND MERGE2_TEST(Fixed64, 17U, Fixed32, 106U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFixed64 = 17U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(dst.oneofFixed64, 17U);
+ XCTAssertEqual(dst.oneofFixed32, 106U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sfixed32, 18, Fixed64, 107U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSfixed32 = 18;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(dst.oneofSfixed32, 18);
+ XCTAssertEqual(dst.oneofFixed64, 107U);
+
+//%PDDM-EXPAND MERGE2_TEST(Sfixed64, 19, Sfixed32, 108)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSfixed64 = 19;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(dst.oneofSfixed64, 19);
+ XCTAssertEqual(dst.oneofSfixed32, 108);
+
+//%PDDM-EXPAND MERGE2_TEST(Float, 20.0f, Sfixed64, 109)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFloat = 20.0f;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(dst.oneofFloat, 20.0f);
+ XCTAssertEqual(dst.oneofSfixed64, 109);
+
+//%PDDM-EXPAND MERGE2_TEST(Double, 21.0, Float, 110.0f)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofDouble = 21.0;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(dst.oneofDouble, 21.0);
+ XCTAssertEqual(dst.oneofFloat, 110.0f);
+
+//%PDDM-EXPAND MERGE2_TEST(Bool, NO, Double, 111.0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofBool = NO;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+ XCTAssertEqual(dst.oneofBool, NO);
+ XCTAssertEqual(dst.oneofDouble, 111.0);
+
+//%PDDM-EXPAND MERGE2_TEST(Enum, Message2_Enum_Bar, Bool, YES)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofEnum = Message2_Enum_Bar;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(dst.oneofEnum, Message2_Enum_Bar);
+ XCTAssertEqual(dst.oneofBool, YES);
+
+//%PDDM-EXPAND-END (14 expansions)
+
+ NSString *oneofStringDefault = @"string";
+ NSData *oneofBytesDefault = [@"data" dataUsingEncoding:NSUTF8StringEncoding];
+
+ src.oneofString = @"foo";
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofString);
+ XCTAssertEqualObjects(dst.oneofString, @"foo");
+ XCTAssertEqual(dst.oneofEnum, Message2_Enum_Baz);
+
+ src.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+ XCTAssertEqualObjects(dst.oneofBytes,
+ [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ XCTAssertEqualObjects(dst.oneofString, oneofStringDefault);
+
+ Message2_OneofGroup *group = [Message2_OneofGroup message];
+ group.a = 666;
+ src.oneofGroup = group;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+ Message2_OneofGroup *mergedGroup = [[dst.oneofGroup retain] autorelease];
+ XCTAssertNotNil(mergedGroup);
+ XCTAssertNotEqual(mergedGroup, group); // Pointer comparision.
+ XCTAssertEqualObjects(mergedGroup, group);
+ XCTAssertEqualObjects(dst.oneofBytes, oneofBytesDefault);
+
+ Message2 *subMessage = [Message2 message];
+ subMessage.optionalInt32 = 777;
+ src.oneofMessage = subMessage;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+ Message2 *mergedSubMessage = [[dst.oneofMessage retain] autorelease];
+ XCTAssertNotNil(mergedSubMessage);
+ XCTAssertNotEqual(mergedSubMessage, subMessage); // Pointer comparision.
+ XCTAssertEqualObjects(mergedSubMessage, subMessage);
+ XCTAssertNotNil(dst.oneofGroup);
+ XCTAssertNotEqual(dst.oneofGroup, mergedGroup); // Pointer comparision.
+
+ // Back to something else ot make sure message clears out ok.
+
+ src.oneofInt32 = 10;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+ XCTAssertNotNil(dst.oneofMessage);
+ XCTAssertNotEqual(dst.oneofMessage,
+ mergedSubMessage); // Pointer comparision.
+
+ //
+ // Test merging in to message/group when they already had something.
+ //
+
+ src.oneofGroup = group;
+ mergedGroup = [Message2_OneofGroup message];
+ mergedGroup.b = 888;
+ dst.oneofGroup = mergedGroup;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+ // Shouldn't have been a new object.
+ XCTAssertEqual(dst.oneofGroup, mergedGroup); // Pointer comparision.
+ XCTAssertEqual(dst.oneofGroup.a, 666); // Pointer comparision.
+ XCTAssertEqual(dst.oneofGroup.b, 888); // Pointer comparision.
+
+ src.oneofMessage = subMessage;
+ mergedSubMessage = [Message2 message];
+ mergedSubMessage.optionalInt64 = 999;
+ dst.oneofMessage = mergedSubMessage;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+ // Shouldn't have been a new object.
+ XCTAssertEqual(dst.oneofMessage, mergedSubMessage); // Pointer comparision.
+ XCTAssertEqual(dst.oneofMessage.optionalInt32, 777); // Pointer comparision.
+ XCTAssertEqual(dst.oneofMessage.optionalInt64, 999); // Pointer comparision.
+}
+
+- (void)testProto3MergeOneof {
+ Message3 *src = [Message3 message];
+ Message3 *dst = [Message3 message];
+
+ //
+ // Make sure whatever is in dst gets cleared out be merging in something else.
+ //
+
+ dst.oneofEnum = Message3_Enum_Bar;
+
+//%PDDM-DEFINE MERGE3_TEST(SET_NAME, SET_VALUE, CLEARED_NAME, CLEARED_DEFAULT)
+//% src.oneof##SET_NAME = SET_VALUE;
+//% [dst mergeFrom:src];
+//% XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_Oneof##SET_NAME);
+//% XCTAssertEqual(dst.oneof##SET_NAME, SET_VALUE);
+//% XCTAssertEqual(dst.oneof##CLEARED_NAME, CLEARED_DEFAULT);
+//%
+//%PDDM-EXPAND MERGE3_TEST(Int32, 10, Enum, Message3_Enum_Foo)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofInt32 = 10;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(dst.oneofInt32, 10);
+ XCTAssertEqual(dst.oneofEnum, Message3_Enum_Foo);
+
+//%PDDM-EXPAND MERGE3_TEST(Int64, 11, Int32, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofInt64 = 11;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(dst.oneofInt64, 11);
+ XCTAssertEqual(dst.oneofInt32, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Uint32, 12U, Int64, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofUint32 = 12U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(dst.oneofUint32, 12U);
+ XCTAssertEqual(dst.oneofInt64, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Uint64, 13U, Uint32, 0U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofUint64 = 13U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(dst.oneofUint64, 13U);
+ XCTAssertEqual(dst.oneofUint32, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sint32, 14, Uint64, 0U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSint32 = 14;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(dst.oneofSint32, 14);
+ XCTAssertEqual(dst.oneofUint64, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sint64, 15, Sint32, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSint64 = 15;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(dst.oneofSint64, 15);
+ XCTAssertEqual(dst.oneofSint32, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Fixed32, 16U, Sint64, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFixed32 = 16U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(dst.oneofFixed32, 16U);
+ XCTAssertEqual(dst.oneofSint64, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Fixed64, 17U, Fixed32, 0U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFixed64 = 17U;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(dst.oneofFixed64, 17U);
+ XCTAssertEqual(dst.oneofFixed32, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sfixed32, 18, Fixed64, 0U)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSfixed32 = 18;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(dst.oneofSfixed32, 18);
+ XCTAssertEqual(dst.oneofFixed64, 0U);
+
+//%PDDM-EXPAND MERGE3_TEST(Sfixed64, 19, Sfixed32, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofSfixed64 = 19;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(dst.oneofSfixed64, 19);
+ XCTAssertEqual(dst.oneofSfixed32, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Float, 20.0f, Sfixed64, 0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofFloat = 20.0f;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(dst.oneofFloat, 20.0f);
+ XCTAssertEqual(dst.oneofSfixed64, 0);
+
+//%PDDM-EXPAND MERGE3_TEST(Double, 21.0, Float, 0.0f)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofDouble = 21.0;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(dst.oneofDouble, 21.0);
+ XCTAssertEqual(dst.oneofFloat, 0.0f);
+
+//%PDDM-EXPAND MERGE3_TEST(Bool, YES, Double, 0.0)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofBool = YES;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+ XCTAssertEqual(dst.oneofBool, YES);
+ XCTAssertEqual(dst.oneofDouble, 0.0);
+
+//%PDDM-EXPAND MERGE3_TEST(Enum, Message3_Enum_Bar, Bool, NO)
+// This block of code is generated, do not edit it directly.
+
+ src.oneofEnum = Message3_Enum_Bar;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(dst.oneofEnum, Message3_Enum_Bar);
+ XCTAssertEqual(dst.oneofBool, NO);
+
+//%PDDM-EXPAND-END (14 expansions)
+
+ NSString *oneofStringDefault = @"";
+ NSData *oneofBytesDefault = [NSData data];
+
+ src.oneofString = @"foo";
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofString);
+ XCTAssertEqualObjects(dst.oneofString, @"foo");
+ XCTAssertEqual(dst.oneofEnum, Message3_Enum_Foo);
+
+ src.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+ XCTAssertEqualObjects(dst.oneofBytes,
+ [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ XCTAssertEqualObjects(dst.oneofString, oneofStringDefault);
+
+
+ Message3 *subMessage = [Message3 message];
+ subMessage.optionalInt32 = 777;
+ src.oneofMessage = subMessage;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+ Message3 *mergedSubMessage = [[dst.oneofMessage retain] autorelease];
+ XCTAssertNotNil(mergedSubMessage);
+ XCTAssertNotEqual(mergedSubMessage, subMessage); // Pointer comparision.
+ XCTAssertEqualObjects(mergedSubMessage, subMessage);
+ XCTAssertEqualObjects(dst.oneofBytes, oneofBytesDefault);
+
+ // Back to something else ot make sure message clears out ok.
+
+ src.oneofInt32 = 10;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+ XCTAssertNotNil(dst.oneofMessage);
+ XCTAssertNotEqual(dst.oneofMessage,
+ mergedSubMessage); // Pointer comparision.
+
+ //
+ // Test merging in to message when they already had something.
+ //
+
+ src.oneofMessage = subMessage;
+ mergedSubMessage = [Message3 message];
+ mergedSubMessage.optionalInt64 = 999;
+ dst.oneofMessage = mergedSubMessage;
+ [dst mergeFrom:src];
+ XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+ // Shouldn't have been a new object.
+ XCTAssertEqual(dst.oneofMessage, mergedSubMessage); // Pointer comparision.
+ XCTAssertEqual(dst.oneofMessage.optionalInt32, 777); // Pointer comparision.
+ XCTAssertEqual(dst.oneofMessage.optionalInt64, 999); // Pointer comparision.
+}
+
+#pragma mark - Subset from from map_tests.cc
+
+// TEST(GeneratedMapFieldTest, CopyFromMessageMap)
+- (void)testMap_CopyFromMessageMap {
+ TestMessageMap *msg1 = [[TestMessageMap alloc] init];
+ TestMessageMap *msg2 = [[TestMessageMap alloc] init];
+
+ TestAllTypes *subMsg = [TestAllTypes message];
+ subMsg.repeatedInt32Array = [GPBInt32Array arrayWithValue:100];
+ msg1.mapInt32Message = [GPBInt32ObjectDictionary dictionary];
+ [msg1.mapInt32Message setValue:subMsg forKey:0];
+ subMsg = nil;
+
+ subMsg = [TestAllTypes message];
+ subMsg.repeatedInt32Array = [GPBInt32Array arrayWithValue:101];
+ msg2.mapInt32Message = [GPBInt32ObjectDictionary dictionary];
+ [msg2.mapInt32Message setValue:subMsg forKey:0];
+ subMsg = nil;
+
+ [msg1 mergeFrom:msg2];
+
+ // Checks repeated field is overwritten.
+ XCTAssertEqual(msg1.mapInt32Message.count, 1U);
+ subMsg = [msg1.mapInt32Message valueForKey:0];
+ XCTAssertNotNil(subMsg);
+ XCTAssertEqual(subMsg.repeatedInt32Array.count, 1U);
+ XCTAssertEqual([subMsg.repeatedInt32Array valueAtIndex:0], 101);
+
+ [msg2 release];
+ [msg1 release];
+}
+
+@end
diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m
new file mode 100644
index 00000000..6ad29ca5
--- /dev/null
+++ b/objectivec/Tests/GPBMessageTests+Runtime.m
@@ -0,0 +1,1978 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+
+@interface MessageRuntimeTests : GPBTestCase
+@end
+
+@implementation MessageRuntimeTests
+
+// TODO(thomasvl): Pull tests over from GPBMessageTests that are runtime
+// specific.
+
+- (void)testProto2HasMethodSupport {
+ NSArray *names = @[
+ @"Int32",
+ @"Int64",
+ @"Uint32",
+ @"Uint64",
+ @"Sint32",
+ @"Sint64",
+ @"Fixed32",
+ @"Fixed64",
+ @"Sfixed32",
+ @"Sfixed64",
+ @"Float",
+ @"Double",
+ @"Bool",
+ @"String",
+ @"Bytes",
+ @"Group",
+ @"Message",
+ @"Enum",
+ ];
+
+ // Proto2 gets:
+ // - has* on all non repeated fields.
+ // - setHas* on all non repeated fields.
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32:
+ SEL hasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"hasOptional%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasOptional%@:", name]);
+ XCTAssertTrue([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertTrue([Message2 instancesRespondToSelector:setHasSel], @"field: %@",
+ name);
+ }
+
+ // Repeated - no has/setHas
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasRepeatedInt32/setHasRepeatedInt32:
+ SEL hasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"hasRepeated%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasRepeated%@:", name]);
+ XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ }
+
+ // Oneofs - no has/setHas
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasOneofInt32/setHasOneofInt32:
+ SEL hasSel =
+ NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasOneof%@:", name]);
+ XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ }
+}
+
+- (void)testProto3HasMethodSupport {
+ NSArray *names = @[
+ @"Int32",
+ @"Int64",
+ @"Uint32",
+ @"Uint64",
+ @"Sint32",
+ @"Sint64",
+ @"Fixed32",
+ @"Fixed64",
+ @"Sfixed32",
+ @"Sfixed64",
+ @"Float",
+ @"Double",
+ @"Bool",
+ @"String",
+ @"Bytes",
+ @"Message",
+ @"Enum",
+ ];
+
+ // Proto3 gets:
+ // - has* on non repeated message fields.
+ // - setHas* on all non repeated message fields.
+
+ // Singlular
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasOptionalInt32/setHasOptionalInt32:
+ SEL hasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"hasOptional%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasOptional%@:", name]);
+ if ([name isEqual:@"Group"] || [name isEqual:@"Message"]) {
+ // Sub messages/groups are the exception.
+ XCTAssertTrue([Message3 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertTrue([Message3 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ } else {
+ XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ }
+ }
+
+ // Repeated - no has/setHas
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasRepeatedInt32/setHasRepeatedInt32:
+ SEL hasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"hasRepeated%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasRepeated%@:", name]);
+ XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ }
+
+ // Oneofs - no has/setHas
+
+ for (NSString *name in names) {
+ // build the selector, i.e. - hasOneofInt32/setHasOneofInt32:
+ SEL hasSel =
+ NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
+ SEL setHasSel = NSSelectorFromString(
+ [NSString stringWithFormat:@"setHasOneof%@:", name]);
+ XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
+ name);
+ XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
+ @"field: %@", name);
+ }
+}
+
+- (void)testProto2SingleFieldHasBehavior {
+ //
+ // Setting to any value including the default value (0) should result has*
+ // being true.
+ //
+
+//%PDDM-DEFINE PROTO2_TEST_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
+//% { // optional##FIELD :: NON_ZERO_VALUE
+//% Message2 *msg = [[Message2 alloc] init];
+//% XCTAssertFalse(msg.hasOptional##FIELD);
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = NON_ZERO_VALUE;
+//% XCTAssertTrue(msg.hasOptional##FIELD);
+//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% [msg release];
+//% }
+//% { // optional##FIELD :: ZERO_VALUE
+//% Message2 *msg = [[Message2 alloc] init];
+//% XCTAssertFalse(msg.hasOptional##FIELD);
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = ZERO_VALUE;
+//% XCTAssertTrue(msg.hasOptional##FIELD);
+//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_Optional##FIELD));
+//% [msg release];
+//% }
+//%
+//%PDDM-DEFINE PROTO2_TEST_HAS_FIELDS()
+//%PROTO2_TEST_HAS_FIELD(Int32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Int64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Uint32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Uint64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sint32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sint64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Fixed32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Fixed64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sfixed32, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Sfixed64, 1, 0)
+//%PROTO2_TEST_HAS_FIELD(Float, 1.0f, 0.0f)
+//%PROTO2_TEST_HAS_FIELD(Double, 1.0, 0.0)
+//%PROTO2_TEST_HAS_FIELD(Bool, YES, NO)
+//%PROTO2_TEST_HAS_FIELD(String, @"foo", @"")
+//%PROTO2_TEST_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data])
+//% //
+//% // Test doesn't apply to optionalGroup/optionalMessage.
+//% //
+//%
+//%PROTO2_TEST_HAS_FIELD(Enum, Message2_Enum_Bar, Message2_Enum_Foo)
+//%PDDM-EXPAND PROTO2_TEST_HAS_FIELDS()
+// This block of code is generated, do not edit it directly.
+
+ { // optionalInt32 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalInt32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+ msg.optionalInt32 = 1;
+ XCTAssertTrue(msg.hasOptionalInt32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+ [msg release];
+ }
+ { // optionalInt32 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalInt32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+ msg.optionalInt32 = 0;
+ XCTAssertTrue(msg.hasOptionalInt32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt32));
+ [msg release];
+ }
+
+ { // optionalInt64 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalInt64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+ msg.optionalInt64 = 1;
+ XCTAssertTrue(msg.hasOptionalInt64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+ [msg release];
+ }
+ { // optionalInt64 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalInt64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+ msg.optionalInt64 = 0;
+ XCTAssertTrue(msg.hasOptionalInt64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalInt64));
+ [msg release];
+ }
+
+ { // optionalUint32 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalUint32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+ msg.optionalUint32 = 1;
+ XCTAssertTrue(msg.hasOptionalUint32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+ [msg release];
+ }
+ { // optionalUint32 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalUint32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+ msg.optionalUint32 = 0;
+ XCTAssertTrue(msg.hasOptionalUint32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint32));
+ [msg release];
+ }
+
+ { // optionalUint64 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalUint64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+ msg.optionalUint64 = 1;
+ XCTAssertTrue(msg.hasOptionalUint64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+ [msg release];
+ }
+ { // optionalUint64 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalUint64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+ msg.optionalUint64 = 0;
+ XCTAssertTrue(msg.hasOptionalUint64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalUint64));
+ [msg release];
+ }
+
+ { // optionalSint32 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSint32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+ msg.optionalSint32 = 1;
+ XCTAssertTrue(msg.hasOptionalSint32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+ [msg release];
+ }
+ { // optionalSint32 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSint32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+ msg.optionalSint32 = 0;
+ XCTAssertTrue(msg.hasOptionalSint32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint32));
+ [msg release];
+ }
+
+ { // optionalSint64 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSint64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+ msg.optionalSint64 = 1;
+ XCTAssertTrue(msg.hasOptionalSint64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+ [msg release];
+ }
+ { // optionalSint64 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSint64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+ msg.optionalSint64 = 0;
+ XCTAssertTrue(msg.hasOptionalSint64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSint64));
+ [msg release];
+ }
+
+ { // optionalFixed32 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFixed32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+ msg.optionalFixed32 = 1;
+ XCTAssertTrue(msg.hasOptionalFixed32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+ [msg release];
+ }
+ { // optionalFixed32 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFixed32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+ msg.optionalFixed32 = 0;
+ XCTAssertTrue(msg.hasOptionalFixed32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed32));
+ [msg release];
+ }
+
+ { // optionalFixed64 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFixed64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+ msg.optionalFixed64 = 1;
+ XCTAssertTrue(msg.hasOptionalFixed64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+ [msg release];
+ }
+ { // optionalFixed64 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFixed64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+ msg.optionalFixed64 = 0;
+ XCTAssertTrue(msg.hasOptionalFixed64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFixed64));
+ [msg release];
+ }
+
+ { // optionalSfixed32 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSfixed32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+ msg.optionalSfixed32 = 1;
+ XCTAssertTrue(msg.hasOptionalSfixed32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+ [msg release];
+ }
+ { // optionalSfixed32 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSfixed32);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+ msg.optionalSfixed32 = 0;
+ XCTAssertTrue(msg.hasOptionalSfixed32);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed32));
+ [msg release];
+ }
+
+ { // optionalSfixed64 :: 1
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSfixed64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+ msg.optionalSfixed64 = 1;
+ XCTAssertTrue(msg.hasOptionalSfixed64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+ [msg release];
+ }
+ { // optionalSfixed64 :: 0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalSfixed64);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+ msg.optionalSfixed64 = 0;
+ XCTAssertTrue(msg.hasOptionalSfixed64);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalSfixed64));
+ [msg release];
+ }
+
+ { // optionalFloat :: 1.0f
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFloat);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+ msg.optionalFloat = 1.0f;
+ XCTAssertTrue(msg.hasOptionalFloat);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+ [msg release];
+ }
+ { // optionalFloat :: 0.0f
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalFloat);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+ msg.optionalFloat = 0.0f;
+ XCTAssertTrue(msg.hasOptionalFloat);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalFloat));
+ [msg release];
+ }
+
+ { // optionalDouble :: 1.0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalDouble);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+ msg.optionalDouble = 1.0;
+ XCTAssertTrue(msg.hasOptionalDouble);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+ [msg release];
+ }
+ { // optionalDouble :: 0.0
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalDouble);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+ msg.optionalDouble = 0.0;
+ XCTAssertTrue(msg.hasOptionalDouble);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalDouble));
+ [msg release];
+ }
+
+ { // optionalBool :: YES
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalBool);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+ msg.optionalBool = YES;
+ XCTAssertTrue(msg.hasOptionalBool);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+ [msg release];
+ }
+ { // optionalBool :: NO
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalBool);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+ msg.optionalBool = NO;
+ XCTAssertTrue(msg.hasOptionalBool);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBool));
+ [msg release];
+ }
+
+ { // optionalString :: @"foo"
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalString);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ msg.optionalString = @"foo";
+ XCTAssertTrue(msg.hasOptionalString);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ [msg release];
+ }
+ { // optionalString :: @""
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalString);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ msg.optionalString = @"";
+ XCTAssertTrue(msg.hasOptionalString);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalString));
+ [msg release];
+ }
+
+ { // optionalBytes :: [@"foo" dataUsingEncoding:NSUTF8StringEncoding]
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalBytes);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertTrue(msg.hasOptionalBytes);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ [msg release];
+ }
+ { // optionalBytes :: [NSData data]
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalBytes);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ msg.optionalBytes = [NSData data];
+ XCTAssertTrue(msg.hasOptionalBytes);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalBytes));
+ [msg release];
+ }
+
+ //
+ // Test doesn't apply to optionalGroup/optionalMessage.
+ //
+
+ { // optionalEnum :: Message2_Enum_Bar
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalEnum);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+ msg.optionalEnum = Message2_Enum_Bar;
+ XCTAssertTrue(msg.hasOptionalEnum);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+ [msg release];
+ }
+ { // optionalEnum :: Message2_Enum_Foo
+ Message2 *msg = [[Message2 alloc] init];
+ XCTAssertFalse(msg.hasOptionalEnum);
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+ msg.optionalEnum = Message2_Enum_Foo;
+ XCTAssertTrue(msg.hasOptionalEnum);
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message2_FieldNumber_OptionalEnum));
+ [msg release];
+ }
+
+//%PDDM-EXPAND-END PROTO2_TEST_HAS_FIELDS()
+}
+
+- (void)testProto3SingleFieldHasBehavior {
+ //
+ // Setting to any value including the default value (0) should result has*
+ // being true.
+ //
+
+//%PDDM-DEFINE PROTO3_TEST_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
+//% { // optional##FIELD
+//% Message3 *msg = [[Message3 alloc] init];
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = NON_ZERO_VALUE;
+//% XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//% msg.optional##FIELD = ZERO_VALUE;
+//% XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_Optional##FIELD));
+//% [msg release];
+//% }
+//%
+//%PDDM-DEFINE PROTO3_TEST_HAS_FIELDS()
+//%PROTO3_TEST_HAS_FIELD(Int32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Int64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Uint32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Uint64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sint32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sint64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Fixed32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Fixed64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sfixed32, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Sfixed64, 1, 0)
+//%PROTO3_TEST_HAS_FIELD(Float, 1.0f, 0.0f)
+//%PROTO3_TEST_HAS_FIELD(Double, 1.0, 0.0)
+//%PROTO3_TEST_HAS_FIELD(Bool, YES, NO)
+//%PROTO3_TEST_HAS_FIELD(String, @"foo", @"")
+//%PROTO3_TEST_HAS_FIELD(Bytes, [@"foo" dataUsingEncoding:NSUTF8StringEncoding], [NSData data])
+//% //
+//% // Test doesn't apply to optionalGroup/optionalMessage.
+//% //
+//%
+//%PROTO3_TEST_HAS_FIELD(Enum, Message3_Enum_Bar, Message3_Enum_Foo)
+//%PDDM-EXPAND PROTO3_TEST_HAS_FIELDS()
+// This block of code is generated, do not edit it directly.
+
+ { // optionalInt32
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt32));
+ msg.optionalInt32 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt32));
+ msg.optionalInt32 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt32));
+ [msg release];
+ }
+
+ { // optionalInt64
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt64));
+ msg.optionalInt64 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt64));
+ msg.optionalInt64 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalInt64));
+ [msg release];
+ }
+
+ { // optionalUint32
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint32));
+ msg.optionalUint32 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint32));
+ msg.optionalUint32 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint32));
+ [msg release];
+ }
+
+ { // optionalUint64
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint64));
+ msg.optionalUint64 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint64));
+ msg.optionalUint64 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalUint64));
+ [msg release];
+ }
+
+ { // optionalSint32
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint32));
+ msg.optionalSint32 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint32));
+ msg.optionalSint32 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint32));
+ [msg release];
+ }
+
+ { // optionalSint64
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint64));
+ msg.optionalSint64 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint64));
+ msg.optionalSint64 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSint64));
+ [msg release];
+ }
+
+ { // optionalFixed32
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed32));
+ msg.optionalFixed32 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed32));
+ msg.optionalFixed32 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed32));
+ [msg release];
+ }
+
+ { // optionalFixed64
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed64));
+ msg.optionalFixed64 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed64));
+ msg.optionalFixed64 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFixed64));
+ [msg release];
+ }
+
+ { // optionalSfixed32
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed32));
+ msg.optionalSfixed32 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed32));
+ msg.optionalSfixed32 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed32));
+ [msg release];
+ }
+
+ { // optionalSfixed64
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed64));
+ msg.optionalSfixed64 = 1;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed64));
+ msg.optionalSfixed64 = 0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalSfixed64));
+ [msg release];
+ }
+
+ { // optionalFloat
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFloat));
+ msg.optionalFloat = 1.0f;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFloat));
+ msg.optionalFloat = 0.0f;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalFloat));
+ [msg release];
+ }
+
+ { // optionalDouble
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalDouble));
+ msg.optionalDouble = 1.0;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalDouble));
+ msg.optionalDouble = 0.0;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalDouble));
+ [msg release];
+ }
+
+ { // optionalBool
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBool));
+ msg.optionalBool = YES;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBool));
+ msg.optionalBool = NO;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBool));
+ [msg release];
+ }
+
+ { // optionalString
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+ msg.optionalString = @"foo";
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+ msg.optionalString = @"";
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalString));
+ [msg release];
+ }
+
+ { // optionalBytes
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+ msg.optionalBytes = [@"foo" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+ msg.optionalBytes = [NSData data];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalBytes));
+ [msg release];
+ }
+
+ //
+ // Test doesn't apply to optionalGroup/optionalMessage.
+ //
+
+ { // optionalEnum
+ Message3 *msg = [[Message3 alloc] init];
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalEnum));
+ msg.optionalEnum = Message3_Enum_Bar;
+ XCTAssertTrue(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalEnum));
+ msg.optionalEnum = Message3_Enum_Foo;
+ XCTAssertFalse(GPBMessageHasFieldNumberSet(msg, Message3_FieldNumber_OptionalEnum));
+ [msg release];
+ }
+
+//%PDDM-EXPAND-END PROTO3_TEST_HAS_FIELDS()
+}
+
+- (void)testAccessingProto2UnknownEnumValues {
+ Message2 *msg = [[Message2 alloc] init];
+
+ // Set it to something non zero, try and confirm it doesn't change.
+
+ msg.optionalEnum = Message2_Enum_Bar;
+ XCTAssertThrowsSpecificNamed(msg.optionalEnum = 666, NSException,
+ NSInvalidArgumentException);
+ XCTAssertEqual(msg.optionalEnum, Message2_Enum_Bar);
+
+ msg.oneofEnum = Message2_Enum_Bar;
+ XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException,
+ NSInvalidArgumentException);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+}
+
+- (void)testAccessingProto3UnknownEnumValues {
+ Message3 *msg = [[Message3 alloc] init];
+
+ // Set it to something non zero, try and confirm it doesn't change.
+
+ msg.optionalEnum = Message3_Enum_Bar;
+ XCTAssertThrowsSpecificNamed(msg.optionalEnum = 666, NSException,
+ NSInvalidArgumentException);
+ XCTAssertEqual(msg.optionalEnum, Message3_Enum_Bar);
+
+ msg.oneofEnum = Message3_Enum_Bar;
+ XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException,
+ NSInvalidArgumentException);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Bar);
+
+ // Set via raw api to confirm it works.
+
+ SetMessage3_OptionalEnum_RawValue(msg, 666);
+ XCTAssertEqual(msg.optionalEnum,
+ Message3_Enum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(Message3_OptionalEnum_RawValue(msg), 666);
+
+ SetMessage3_OneofEnum_RawValue(msg, 666);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(Message3_OneofEnum_RawValue(msg), 666);
+
+ [msg release];
+}
+
+- (void)testProto2OneofBasicBehaviors {
+ Message2 *msg = [[Message2 alloc] init];
+
+ NSString *oneofStringDefault = @"string";
+ NSData *oneofBytesDefault = [@"data" dataUsingEncoding:NSUTF8StringEncoding];
+
+ // Nothing set.
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+
+ // Set, check the case, check everyone has default but the one, confirm case
+ // didn't change.
+
+ msg.oneofInt32 = 1;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(msg.oneofInt32, 1);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+
+ msg.oneofInt64 = 2;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 2);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+
+ msg.oneofUint32 = 3;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 3U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+
+ msg.oneofUint64 = 4;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 4U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+
+ msg.oneofSint32 = 5;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 5);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+
+ msg.oneofSint64 = 6;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 6);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+
+ msg.oneofFixed32 = 7;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 7U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+
+ msg.oneofFixed64 = 8;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 8U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+
+ msg.oneofSfixed32 = 9;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 9);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+
+ msg.oneofSfixed64 = 10;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 10);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+
+ msg.oneofFloat = 11.0f;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 11.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+
+ msg.oneofDouble = 12.0;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 12.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+
+ msg.oneofBool = NO;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+
+ msg.oneofString = @"foo";
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, @"foo");
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString);
+
+ msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes,
+ [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+
+ Message2_OneofGroup *group = [Message2_OneofGroup message];
+ msg.oneofGroup = group;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertEqual(msg.oneofGroup, group); // Pointer compare.
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+
+ Message2 *subMessage = [Message2 message];
+ msg.oneofMessage = subMessage;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotEqual(msg.oneofGroup, group); // Pointer compare.
+ XCTAssertEqual(msg.oneofMessage, subMessage); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+
+ msg.oneofEnum = Message2_Enum_Bar;
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(msg.oneofInt32, 100);
+ XCTAssertEqual(msg.oneofInt64, 101);
+ XCTAssertEqual(msg.oneofUint32, 102U);
+ XCTAssertEqual(msg.oneofUint64, 103U);
+ XCTAssertEqual(msg.oneofSint32, 104);
+ XCTAssertEqual(msg.oneofSint64, 105);
+ XCTAssertEqual(msg.oneofFixed32, 106U);
+ XCTAssertEqual(msg.oneofFixed64, 107U);
+ XCTAssertEqual(msg.oneofSfixed32, 108);
+ XCTAssertEqual(msg.oneofSfixed64, 109);
+ XCTAssertEqual(msg.oneofFloat, 110.0f);
+ XCTAssertEqual(msg.oneofDouble, 111.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofGroup);
+ XCTAssertNotEqual(msg.oneofGroup, group); // Pointer compare.
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertNotEqual(msg.oneofMessage, subMessage); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+
+ // Test setting/calling clear clearing.
+
+ [msg release];
+ msg = [[Message2 alloc] init];
+
+ uint32_t values[] = {
+ Message2_O_OneOfCase_OneofInt32,
+ Message2_O_OneOfCase_OneofInt64,
+ Message2_O_OneOfCase_OneofUint32,
+ Message2_O_OneOfCase_OneofUint64,
+ Message2_O_OneOfCase_OneofSint32,
+ Message2_O_OneOfCase_OneofSint64,
+ Message2_O_OneOfCase_OneofFixed32,
+ Message2_O_OneOfCase_OneofFixed64,
+ Message2_O_OneOfCase_OneofSfixed32,
+ Message2_O_OneOfCase_OneofSfixed64,
+ Message2_O_OneOfCase_OneofFloat,
+ Message2_O_OneOfCase_OneofDouble,
+ Message2_O_OneOfCase_OneofBool,
+ Message2_O_OneOfCase_OneofString,
+ Message2_O_OneOfCase_OneofBytes,
+ Message2_O_OneOfCase_OneofGroup,
+ Message2_O_OneOfCase_OneofMessage,
+ Message2_O_OneOfCase_OneofEnum,
+ };
+
+ for (size_t i = 0; i < (sizeof(values) / sizeof((values[0]))); ++i) {
+ switch (values[i]) {
+ case Message2_O_OneOfCase_OneofInt32:
+ msg.oneofInt32 = 1;
+ break;
+ case Message2_O_OneOfCase_OneofInt64:
+ msg.oneofInt64 = 2;
+ break;
+ case Message2_O_OneOfCase_OneofUint32:
+ msg.oneofUint32 = 3;
+ break;
+ case Message2_O_OneOfCase_OneofUint64:
+ msg.oneofUint64 = 4;
+ break;
+ case Message2_O_OneOfCase_OneofSint32:
+ msg.oneofSint32 = 5;
+ break;
+ case Message2_O_OneOfCase_OneofSint64:
+ msg.oneofSint64 = 6;
+ break;
+ case Message2_O_OneOfCase_OneofFixed32:
+ msg.oneofFixed32 = 7;
+ break;
+ case Message2_O_OneOfCase_OneofFixed64:
+ msg.oneofFixed64 = 8;
+ break;
+ case Message2_O_OneOfCase_OneofSfixed32:
+ msg.oneofSfixed32 = 9;
+ break;
+ case Message2_O_OneOfCase_OneofSfixed64:
+ msg.oneofSfixed64 = 10;
+ break;
+ case Message2_O_OneOfCase_OneofFloat:
+ msg.oneofFloat = 11.0f;
+ break;
+ case Message2_O_OneOfCase_OneofDouble:
+ msg.oneofDouble = 12.0;
+ break;
+ case Message2_O_OneOfCase_OneofBool:
+ msg.oneofBool = YES;
+ break;
+ case Message2_O_OneOfCase_OneofString:
+ msg.oneofString = @"foo";
+ break;
+ case Message2_O_OneOfCase_OneofBytes:
+ msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ break;
+ case Message2_O_OneOfCase_OneofGroup:
+ msg.oneofGroup = group;
+ break;
+ case Message2_O_OneOfCase_OneofMessage:
+ msg.oneofMessage = subMessage;
+ break;
+ case Message2_O_OneOfCase_OneofEnum:
+ msg.oneofEnum = Message2_Enum_Bar;
+ break;
+ default:
+ XCTFail(@"shouldn't happen, loop: %zd", i);
+ break;
+ }
+
+ XCTAssertEqual(msg.oOneOfCase, values[i], "Loop: %zd", i);
+ // No need to check the value was set, the above tests did that.
+ Message2_ClearOOneOfCase(msg);
+ // Nothing in the case.
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase,
+ "Loop: %zd", i);
+ // Confirm everything is back to defaults after a clear.
+ XCTAssertEqual(msg.oneofInt32, 100, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofInt64, 101, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint32, 102U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint64, 103U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint32, 104, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint64, 105, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed32, 106U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed64, 107U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed32, 108, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed64, 109, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFloat, 110.0f, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofDouble, 111.0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofBool, YES, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault, "Loop: %zd", i);
+ XCTAssertNotNil(msg.oneofGroup, "Loop: %zd", i);
+ XCTAssertNotEqual(msg.oneofGroup, group, "Loop: %zd",
+ i); // Pointer compare.
+ XCTAssertNotNil(msg.oneofMessage, "Loop: %zd", i);
+ XCTAssertNotEqual(msg.oneofMessage, subMessage, "Loop: %zd",
+ i); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz, "Loop: %zd", i);
+ }
+
+ [msg release];
+}
+
+- (void)testProto3OneofBasicBehaviors {
+ Message3 *msg = [[Message3 alloc] init];
+
+ NSString *oneofStringDefault = @"";
+ NSData *oneofBytesDefault = [NSData data];
+
+ // Nothing set.
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+
+ // Set, check the case, check everyone has default but the one, confirm case
+ // didn't change.
+
+ msg.oneofInt32 = 1;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(msg.oneofInt32, 1);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+
+ msg.oneofInt64 = 2;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 2);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+
+ msg.oneofUint32 = 3;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 3U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+
+ msg.oneofUint64 = 4;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 4U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+
+ msg.oneofSint32 = 5;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 5);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+
+ msg.oneofSint64 = 6;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 6);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+
+ msg.oneofFixed32 = 7;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 7U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+
+ msg.oneofFixed64 = 8;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 8U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+
+ msg.oneofSfixed32 = 9;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 9);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+
+ msg.oneofSfixed64 = 10;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 10);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+
+ msg.oneofFloat = 11.0f;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 11.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+
+ msg.oneofDouble = 12.0;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 12.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+
+ msg.oneofBool = YES;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, YES);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+
+ msg.oneofString = @"foo";
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, @"foo");
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString);
+
+ msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes,
+ [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+
+ Message3 *subMessage = [Message3 message];
+ msg.oneofMessage = subMessage;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertEqual(msg.oneofMessage, subMessage); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+
+ msg.oneofEnum = Message3_Enum_Bar;
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(msg.oneofInt32, 0);
+ XCTAssertEqual(msg.oneofInt64, 0);
+ XCTAssertEqual(msg.oneofUint32, 0U);
+ XCTAssertEqual(msg.oneofUint64, 0U);
+ XCTAssertEqual(msg.oneofSint32, 0);
+ XCTAssertEqual(msg.oneofSint64, 0);
+ XCTAssertEqual(msg.oneofFixed32, 0U);
+ XCTAssertEqual(msg.oneofFixed64, 0U);
+ XCTAssertEqual(msg.oneofSfixed32, 0);
+ XCTAssertEqual(msg.oneofSfixed64, 0);
+ XCTAssertEqual(msg.oneofFloat, 0.0f);
+ XCTAssertEqual(msg.oneofDouble, 0.0);
+ XCTAssertEqual(msg.oneofBool, NO);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault);
+ XCTAssertNotNil(msg.oneofMessage);
+ XCTAssertNotEqual(msg.oneofMessage, subMessage); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Bar);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+
+ // Test setting/calling clear clearing.
+
+ [msg release];
+ msg = [[Message3 alloc] init];
+
+ uint32_t values[] = {
+ Message3_O_OneOfCase_OneofInt32,
+ Message3_O_OneOfCase_OneofInt64,
+ Message3_O_OneOfCase_OneofUint32,
+ Message3_O_OneOfCase_OneofUint64,
+ Message3_O_OneOfCase_OneofSint32,
+ Message3_O_OneOfCase_OneofSint64,
+ Message3_O_OneOfCase_OneofFixed32,
+ Message3_O_OneOfCase_OneofFixed64,
+ Message3_O_OneOfCase_OneofSfixed32,
+ Message3_O_OneOfCase_OneofSfixed64,
+ Message3_O_OneOfCase_OneofFloat,
+ Message3_O_OneOfCase_OneofDouble,
+ Message3_O_OneOfCase_OneofBool,
+ Message3_O_OneOfCase_OneofString,
+ Message3_O_OneOfCase_OneofBytes,
+ Message3_O_OneOfCase_OneofMessage,
+ Message3_O_OneOfCase_OneofEnum,
+ };
+
+ for (size_t i = 0; i < (sizeof(values) / sizeof((values[0]))); ++i) {
+ switch (values[i]) {
+ case Message3_O_OneOfCase_OneofInt32:
+ msg.oneofInt32 = 1;
+ break;
+ case Message3_O_OneOfCase_OneofInt64:
+ msg.oneofInt64 = 2;
+ break;
+ case Message3_O_OneOfCase_OneofUint32:
+ msg.oneofUint32 = 3;
+ break;
+ case Message3_O_OneOfCase_OneofUint64:
+ msg.oneofUint64 = 4;
+ break;
+ case Message3_O_OneOfCase_OneofSint32:
+ msg.oneofSint32 = 5;
+ break;
+ case Message3_O_OneOfCase_OneofSint64:
+ msg.oneofSint64 = 6;
+ break;
+ case Message3_O_OneOfCase_OneofFixed32:
+ msg.oneofFixed32 = 7;
+ break;
+ case Message3_O_OneOfCase_OneofFixed64:
+ msg.oneofFixed64 = 8;
+ break;
+ case Message3_O_OneOfCase_OneofSfixed32:
+ msg.oneofSfixed32 = 9;
+ break;
+ case Message3_O_OneOfCase_OneofSfixed64:
+ msg.oneofSfixed64 = 10;
+ break;
+ case Message3_O_OneOfCase_OneofFloat:
+ msg.oneofFloat = 11.0f;
+ break;
+ case Message3_O_OneOfCase_OneofDouble:
+ msg.oneofDouble = 12.0;
+ break;
+ case Message3_O_OneOfCase_OneofBool:
+ msg.oneofBool = YES;
+ break;
+ case Message3_O_OneOfCase_OneofString:
+ msg.oneofString = @"foo";
+ break;
+ case Message3_O_OneOfCase_OneofBytes:
+ msg.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ break;
+ case Message3_O_OneOfCase_OneofMessage:
+ msg.oneofMessage = subMessage;
+ break;
+ case Message3_O_OneOfCase_OneofEnum:
+ msg.oneofEnum = Message3_Enum_Baz;
+ break;
+ default:
+ XCTFail(@"shouldn't happen, loop: %zd", i);
+ break;
+ }
+
+ XCTAssertEqual(msg.oOneOfCase, values[i], "Loop: %zd", i);
+ // No need to check the value was set, the above tests did that.
+ Message3_ClearOOneOfCase(msg);
+ // Nothing in the case.
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase,
+ "Loop: %zd", i);
+ // Confirm everything is back to defaults after a clear.
+ XCTAssertEqual(msg.oneofInt32, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofInt64, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint32, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofUint64, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint32, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSint64, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed32, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFixed64, 0U, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed32, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofSfixed64, 0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofFloat, 0.0f, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofDouble, 0.0, "Loop: %zd", i);
+ XCTAssertEqual(msg.oneofBool, NO, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofString, oneofStringDefault, "Loop: %zd", i);
+ XCTAssertEqualObjects(msg.oneofBytes, oneofBytesDefault, "Loop: %zd", i);
+ XCTAssertNotNil(msg.oneofMessage, "Loop: %zd", i);
+ XCTAssertNotEqual(msg.oneofMessage, subMessage, "Loop: %zd",
+ i); // Pointer compare.
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo, "Loop: %zd", i);
+ }
+
+ [msg release];
+}
+
+- (void)testCopyingMakesUniqueObjects {
+ const int repeatCount = 5;
+ TestAllTypes *msg1 = [TestAllTypes message];
+ [self setAllFields:msg1 repeatedCount:repeatCount];
+
+ TestAllTypes *msg2 = [[msg1 copy] autorelease];
+
+ XCTAssertNotEqual(msg1, msg2); // Ptr compare, new object.
+ XCTAssertEqualObjects(msg1, msg2); // Equal values.
+
+ // Pointer comparisions, different objects.
+
+ XCTAssertNotEqual(msg1.optionalGroup, msg2.optionalGroup);
+ XCTAssertNotEqual(msg1.optionalNestedMessage, msg2.optionalNestedMessage);
+ XCTAssertNotEqual(msg1.optionalForeignMessage, msg2.optionalForeignMessage);
+ XCTAssertNotEqual(msg1.optionalImportMessage, msg2.optionalImportMessage);
+
+ XCTAssertNotEqual(msg1.repeatedInt32Array, msg2.repeatedInt32Array);
+ XCTAssertNotEqual(msg1.repeatedInt64Array, msg2.repeatedInt64Array);
+ XCTAssertNotEqual(msg1.repeatedUint32Array, msg2.repeatedUint32Array);
+ XCTAssertNotEqual(msg1.repeatedUint64Array, msg2.repeatedUint64Array);
+ XCTAssertNotEqual(msg1.repeatedSint32Array, msg2.repeatedSint32Array);
+ XCTAssertNotEqual(msg1.repeatedSint64Array, msg2.repeatedSint64Array);
+ XCTAssertNotEqual(msg1.repeatedFixed32Array, msg2.repeatedFixed32Array);
+ XCTAssertNotEqual(msg1.repeatedFixed64Array, msg2.repeatedFixed64Array);
+ XCTAssertNotEqual(msg1.repeatedSfixed32Array, msg2.repeatedSfixed32Array);
+ XCTAssertNotEqual(msg1.repeatedSfixed64Array, msg2.repeatedSfixed64Array);
+ XCTAssertNotEqual(msg1.repeatedFloatArray, msg2.repeatedFloatArray);
+ XCTAssertNotEqual(msg1.repeatedDoubleArray, msg2.repeatedDoubleArray);
+ XCTAssertNotEqual(msg1.repeatedBoolArray, msg2.repeatedBoolArray);
+ XCTAssertNotEqual(msg1.repeatedStringArray, msg2.repeatedStringArray);
+ XCTAssertNotEqual(msg1.repeatedBytesArray, msg2.repeatedBytesArray);
+ XCTAssertNotEqual(msg1.repeatedGroupArray, msg2.repeatedGroupArray);
+ XCTAssertNotEqual(msg1.repeatedNestedMessageArray,
+ msg2.repeatedNestedMessageArray);
+ XCTAssertNotEqual(msg1.repeatedForeignMessageArray,
+ msg2.repeatedForeignMessageArray);
+ XCTAssertNotEqual(msg1.repeatedImportMessageArray,
+ msg2.repeatedImportMessageArray);
+ XCTAssertNotEqual(msg1.repeatedNestedEnumArray, msg2.repeatedNestedEnumArray);
+ XCTAssertNotEqual(msg1.repeatedForeignEnumArray,
+ msg2.repeatedForeignEnumArray);
+ XCTAssertNotEqual(msg1.repeatedImportEnumArray, msg2.repeatedImportEnumArray);
+ XCTAssertNotEqual(msg1.repeatedStringPieceArray,
+ msg2.repeatedStringPieceArray);
+ XCTAssertNotEqual(msg1.repeatedCordArray, msg2.repeatedCordArray);
+
+ for (int i = 0; i < repeatCount; i++) {
+ XCTAssertNotEqual(msg1.repeatedNestedMessageArray[i],
+ msg2.repeatedNestedMessageArray[i]);
+ XCTAssertNotEqual(msg1.repeatedForeignMessageArray[i],
+ msg2.repeatedForeignMessageArray[i]);
+ XCTAssertNotEqual(msg1.repeatedImportMessageArray[i],
+ msg2.repeatedImportMessageArray[i]);
+ }
+}
+
+- (void)testCopyingMapsMakesUniqueObjects {
+ TestMap *msg1 = [TestMap message];
+ [self setAllMapFields:msg1 numEntries:5];
+
+ TestMap *msg2 = [[msg1 copy] autorelease];
+
+ XCTAssertNotEqual(msg1, msg2); // Ptr compare, new object.
+ XCTAssertEqualObjects(msg1, msg2); // Equal values.
+
+ // Pointer comparisions, different objects.
+ XCTAssertNotEqual(msg1.mapInt32Int32, msg2.mapInt32Int32);
+ XCTAssertNotEqual(msg1.mapInt64Int64, msg2.mapInt64Int64);
+ XCTAssertNotEqual(msg1.mapUint32Uint32, msg2.mapUint32Uint32);
+ XCTAssertNotEqual(msg1.mapUint64Uint64, msg2.mapUint64Uint64);
+ XCTAssertNotEqual(msg1.mapSint32Sint32, msg2.mapSint32Sint32);
+ XCTAssertNotEqual(msg1.mapSint64Sint64, msg2.mapSint64Sint64);
+ XCTAssertNotEqual(msg1.mapFixed32Fixed32, msg2.mapFixed32Fixed32);
+ XCTAssertNotEqual(msg1.mapFixed64Fixed64, msg2.mapFixed64Fixed64);
+ XCTAssertNotEqual(msg1.mapSfixed32Sfixed32, msg2.mapSfixed32Sfixed32);
+ XCTAssertNotEqual(msg1.mapSfixed64Sfixed64, msg2.mapSfixed64Sfixed64);
+ XCTAssertNotEqual(msg1.mapInt32Float, msg2.mapInt32Float);
+ XCTAssertNotEqual(msg1.mapInt32Double, msg2.mapInt32Double);
+ XCTAssertNotEqual(msg1.mapBoolBool, msg2.mapBoolBool);
+ XCTAssertNotEqual(msg1.mapStringString, msg2.mapStringString);
+ XCTAssertNotEqual(msg1.mapInt32Bytes, msg2.mapInt32Bytes);
+ XCTAssertNotEqual(msg1.mapInt32Enum, msg2.mapInt32Enum);
+ XCTAssertNotEqual(msg1.mapInt32ForeignMessage, msg2.mapInt32ForeignMessage);
+
+ // Ensure the messages are unique per map.
+ [msg1.mapInt32ForeignMessage
+ enumerateKeysAndValuesUsingBlock:^(int32_t key, id value, BOOL *stop) {
+#pragma unused(stop)
+ ForeignMessage *subMsg2 = [msg2.mapInt32ForeignMessage valueForKey:key];
+ XCTAssertNotEqual(value, subMsg2); // Ptr compare, new object.
+ }];
+}
+
+#pragma mark - Subset from from map_tests.cc
+
+// TEST(GeneratedMapFieldTest, IsInitialized)
+- (void)testMap_IsInitialized {
+ TestRequiredMessageMap *msg = [[TestRequiredMessageMap alloc] init];
+
+ // Add an uninitialized message.
+ TestRequired *subMsg = [[TestRequired alloc] init];
+ msg.mapField = [GPBInt32ObjectDictionary dictionary];
+ [msg.mapField setValue:subMsg forKey:0];
+ XCTAssertFalse(msg.initialized);
+
+ // Initialize uninitialized message
+ subMsg.a = 0;
+ subMsg.b = 0;
+ subMsg.c = 0;
+ XCTAssertTrue(msg.initialized);
+
+ [subMsg release];
+ [msg release];
+}
+
+@end
diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m
new file mode 100644
index 00000000..ddc2ae19
--- /dev/null
+++ b/objectivec/Tests/GPBMessageTests+Serialization.m
@@ -0,0 +1,838 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapProto2Unittest.pbobjc.h"
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/UnittestDropUnknownFields.pbobjc.h"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+static NSData *DataFromCStr(const char *str) {
+ return [NSData dataWithBytes:str length:strlen(str)];
+}
+
+@interface MessageSerializationTests : GPBTestCase
+@end
+
+@implementation MessageSerializationTests
+
+// TODO(thomasvl): Pull tests over from GPBMessageTests that are serialization
+// specific.
+
+- (void)testProto3SerializationHandlingDefaults {
+ // Proto2 covered in other tests.
+
+ Message3 *msg = [[Message3 alloc] init];
+
+ // Add defaults, no output.
+
+ NSData *data = [msg data];
+ XCTAssertEqual([data length], 0U);
+
+ // All zeros, still nothing.
+
+ msg.optionalInt32 = 0;
+ msg.optionalInt64 = 0;
+ msg.optionalUint32 = 0;
+ msg.optionalUint64 = 0;
+ msg.optionalSint32 = 0;
+ msg.optionalSint64 = 0;
+ msg.optionalFixed32 = 0;
+ msg.optionalFixed64 = 0;
+ msg.optionalSfixed32 = 0;
+ msg.optionalSfixed64 = 0;
+ msg.optionalFloat = 0.0f;
+ msg.optionalDouble = 0.0;
+ msg.optionalBool = NO;
+ msg.optionalString = @"";
+ msg.optionalBytes = [NSData data];
+ msg.optionalEnum = Message3_Enum_Foo; // first value
+
+ data = [msg data];
+ XCTAssertEqual([data length], 0U);
+
+ // The two that also take nil as nothing.
+
+ msg.optionalString = nil;
+ msg.optionalBytes = nil;
+
+ data = [msg data];
+ XCTAssertEqual([data length], 0U);
+
+ // Set one field...
+
+ msg.optionalInt32 = 1;
+
+ data = [msg data];
+ const uint8_t expectedBytes[] = {0x08, 0x01};
+ NSData *expected = [NSData dataWithBytes:expectedBytes length:2];
+ XCTAssertEqualObjects(data, expected);
+
+ // Back to zero...
+
+ msg.optionalInt32 = 0;
+
+ data = [msg data];
+ XCTAssertEqual([data length], 0U);
+
+ [msg release];
+}
+
+- (void)testProto3DroppingUnknownFields {
+ DropUnknownsFooWithExtraFields *fooWithExtras =
+ [[DropUnknownsFooWithExtraFields alloc] init];
+
+ fooWithExtras.int32Value = 1;
+ fooWithExtras.enumValue = DropUnknownsFooWithExtraFields_NestedEnum_Baz;
+ fooWithExtras.extraInt32Value = 2;
+
+ DropUnknownsFoo *foo = [DropUnknownsFoo parseFromData:[fooWithExtras data]];
+
+ XCTAssertEqual(foo.int32Value, 1);
+ XCTAssertEqual(foo.enumValue, DropUnknownsFoo_NestedEnum_Baz);
+ // Nothing should end up in the unknowns.
+ XCTAssertEqual([foo.unknownFields countOfFields], 0U);
+
+ [fooWithExtras release];
+ fooWithExtras = [DropUnknownsFooWithExtraFields parseFromData:[foo data]];
+ XCTAssertEqual(fooWithExtras.int32Value, 1);
+ XCTAssertEqual(fooWithExtras.enumValue,
+ DropUnknownsFooWithExtraFields_NestedEnum_Baz);
+ // And the extra value is gone (back to the default).
+ XCTAssertEqual(fooWithExtras.extraInt32Value, 0);
+ XCTAssertEqual([foo.unknownFields countOfFields], 0U);
+}
+
+- (void)testProto2UnknownEnumToUnknownField {
+ Message3 *orig = [[Message3 alloc] init];
+
+ orig.optionalEnum = Message3_Enum_Extra3;
+ orig.repeatedEnumArray =
+ [GPBEnumArray arrayWithValidationFunction:Message3_Enum_IsValidValue
+ rawValue:Message3_Enum_Extra3];
+ orig.repeatedPackedEnumArray =
+ [GPBEnumArray arrayWithValidationFunction:Message3_Enum_IsValidValue
+ rawValue:Message3_Enum_Extra3];
+ orig.oneofEnum = Message3_Enum_Extra3;
+
+ Message2 *msg = [[Message2 alloc] initWithData:[orig data]];
+
+ // None of the fields should be set.
+
+ XCTAssertFalse(msg.hasOptionalEnum);
+ XCTAssertEqual(msg.repeatedEnumArray.count, 0U);
+ XCTAssertEqual(msg.repeatedPackedEnumArray.count, 0U);
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase);
+
+ // All the values should be in unknown fields.
+
+ GPBUnknownFieldSet *unknownFields = msg.unknownFields;
+
+ XCTAssertEqual([unknownFields countOfFields], 4U);
+ XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OptionalEnum]);
+ XCTAssertTrue(
+ [unknownFields hasField:Message2_FieldNumber_RepeatedEnumArray]);
+ XCTAssertTrue(
+ [unknownFields hasField:Message2_FieldNumber_RepeatedPackedEnumArray]);
+ XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OneofEnum]);
+
+ GPBField *field = [unknownFields getField:Message2_FieldNumber_OptionalEnum];
+ XCTAssertEqual(field.varintList.count, 1U);
+ XCTAssertEqual([field.varintList valueAtIndex:0],
+ (uint64_t)Message3_Enum_Extra3);
+
+ field = [unknownFields getField:Message2_FieldNumber_RepeatedEnumArray];
+ XCTAssertEqual(field.varintList.count, 1U);
+ XCTAssertEqual([field.varintList valueAtIndex:0],
+ (uint64_t)Message3_Enum_Extra3);
+
+ field = [unknownFields getField:Message2_FieldNumber_RepeatedPackedEnumArray];
+ XCTAssertEqual(field.varintList.count, 1U);
+ XCTAssertEqual([field.varintList valueAtIndex:0],
+ (uint64_t)Message3_Enum_Extra3);
+
+ field = [unknownFields getField:Message2_FieldNumber_OneofEnum];
+ XCTAssertEqual(field.varintList.count, 1U);
+ XCTAssertEqual([field.varintList valueAtIndex:0],
+ (uint64_t)Message3_Enum_Extra3);
+
+ [msg release];
+ [orig release];
+}
+
+- (void)testProto3UnknownEnumPreserving {
+ UnknownEnumsMyMessagePlusExtra *orig =
+ [UnknownEnumsMyMessagePlusExtra message];
+
+ orig.e = UnknownEnumsMyEnumPlusExtra_EExtra;
+ orig.repeatedEArray = [GPBEnumArray
+ arrayWithValidationFunction:UnknownEnumsMyEnumPlusExtra_IsValidValue
+ rawValue:UnknownEnumsMyEnumPlusExtra_EExtra];
+ orig.repeatedPackedEArray = [GPBEnumArray
+ arrayWithValidationFunction:UnknownEnumsMyEnumPlusExtra_IsValidValue
+ rawValue:UnknownEnumsMyEnumPlusExtra_EExtra];
+ orig.oneofE1 = UnknownEnumsMyEnumPlusExtra_EExtra;
+
+ // Everything should be there via raw values.
+
+ UnknownEnumsMyMessage *msg =
+ [UnknownEnumsMyMessage parseFromData:[orig data]];
+
+ XCTAssertEqual(msg.e, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(UnknownEnumsMyMessage_E_RawValue(msg),
+ UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(msg.repeatedEArray.count, 1U);
+ XCTAssertEqual([msg.repeatedEArray valueAtIndex:0],
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([msg.repeatedEArray rawValueAtIndex:0],
+ (UnknownEnumsMyEnum)UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(msg.repeatedPackedEArray.count, 1U);
+ XCTAssertEqual([msg.repeatedPackedEArray valueAtIndex:0],
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual([msg.repeatedPackedEArray rawValueAtIndex:0],
+ (UnknownEnumsMyEnum)UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(msg.oneofE1,
+ UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+ XCTAssertEqual(UnknownEnumsMyMessage_OneofE1_RawValue(msg),
+ UnknownEnumsMyEnumPlusExtra_EExtra);
+
+ // Everything should go out and come back.
+
+ orig = [UnknownEnumsMyMessagePlusExtra parseFromData:[msg data]];
+
+ XCTAssertEqual(orig.e, UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(orig.repeatedEArray.count, 1U);
+ XCTAssertEqual([orig.repeatedEArray valueAtIndex:0],
+ UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(orig.repeatedPackedEArray.count, 1U);
+ XCTAssertEqual([orig.repeatedPackedEArray valueAtIndex:0],
+ UnknownEnumsMyEnumPlusExtra_EExtra);
+ XCTAssertEqual(orig.oneofE1, UnknownEnumsMyEnumPlusExtra_EExtra);
+}
+
+//%PDDM-DEFINE TEST_ROUNDTRIP_ONEOF(MESSAGE, FIELD, VALUE)
+//%TEST_ROUNDTRIP_ONEOF_ADV(MESSAGE, FIELD, VALUE, )
+//%PDDM-DEFINE TEST_ROUNDTRIP_ONEOF_ADV(MESSAGE, FIELD, VALUE, EQ_SUFFIX)
+//% { // oneof##FIELD
+//% MESSAGE *orig = [[MESSAGE alloc] init];
+//% orig.oneof##FIELD = VALUE;
+//% XCTAssertEqual(orig.oOneOfCase, MESSAGE##_O_OneOfCase_Oneof##FIELD);
+//% MESSAGE *msg = [MESSAGE parseFromData:[orig data]];
+//% XCTAssertEqual(msg.oOneOfCase, MESSAGE##_O_OneOfCase_Oneof##FIELD);
+//% XCTAssertEqual##EQ_SUFFIX(msg.oneof##FIELD, VALUE);
+//% [orig release];
+//% }
+//%
+//%PDDM-DEFINE TEST_ROUNDTRIP_ONEOFS(SYNTAX, BOOL_NON_DEFAULT)
+//%- (void)testProto##SYNTAX##RoundTripOneof {
+//%
+//%GROUP_INIT##SYNTAX() Message##SYNTAX *subMessage = [[Message##SYNTAX alloc] init];
+//% XCTAssertNotNil(subMessage);
+//% subMessage.optionalInt32 = 666;
+//%
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Int32, 1)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Int64, 2)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Uint32, 3U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Uint64, 4U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sint32, 5)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sint64, 6)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Fixed32, 7U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Fixed64, 8U)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sfixed32, 9)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Sfixed64, 10)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Float, 11.0f)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Double, 12.0)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Bool, BOOL_NON_DEFAULT)
+//%TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, String, @"foo", Objects)
+//%TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, Bytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding], Objects)
+//%GROUP_TEST##SYNTAX()TEST_ROUNDTRIP_ONEOF_ADV(Message##SYNTAX, Message, subMessage, Objects)
+//%TEST_ROUNDTRIP_ONEOF(Message##SYNTAX, Enum, Message2_Enum_Bar)
+//%GROUP_CLEANUP##SYNTAX() [subMessage release];
+//%}
+//%
+//%PDDM-DEFINE GROUP_INIT2()
+//% Message2_OneofGroup *group = [[Message2_OneofGroup alloc] init];
+//% XCTAssertNotNil(group);
+//% group.a = 777;
+//%
+//%PDDM-DEFINE GROUP_CLEANUP2()
+//% [group release];
+//%
+//%PDDM-DEFINE GROUP_TEST2()
+//%TEST_ROUNDTRIP_ONEOF_ADV(Message2, Group, group, Objects)
+//%
+//%PDDM-DEFINE GROUP_INIT3()
+// Empty
+//%PDDM-DEFINE GROUP_CLEANUP3()
+// Empty
+//%PDDM-DEFINE GROUP_TEST3()
+//% // Not "group" in proto3.
+//%
+//%
+//%PDDM-EXPAND TEST_ROUNDTRIP_ONEOFS(2, NO)
+// This block of code is generated, do not edit it directly.
+
+- (void)testProto2RoundTripOneof {
+
+ Message2_OneofGroup *group = [[Message2_OneofGroup alloc] init];
+ XCTAssertNotNil(group);
+ group.a = 777;
+ Message2 *subMessage = [[Message2 alloc] init];
+ XCTAssertNotNil(subMessage);
+ subMessage.optionalInt32 = 666;
+
+ { // oneofInt32
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofInt32 = 1;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(msg.oneofInt32, 1);
+ [orig release];
+ }
+
+ { // oneofInt64
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofInt64 = 2;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(msg.oneofInt64, 2);
+ [orig release];
+ }
+
+ { // oneofUint32
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofUint32 = 3U;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(msg.oneofUint32, 3U);
+ [orig release];
+ }
+
+ { // oneofUint64
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofUint64 = 4U;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(msg.oneofUint64, 4U);
+ [orig release];
+ }
+
+ { // oneofSint32
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofSint32 = 5;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(msg.oneofSint32, 5);
+ [orig release];
+ }
+
+ { // oneofSint64
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofSint64 = 6;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(msg.oneofSint64, 6);
+ [orig release];
+ }
+
+ { // oneofFixed32
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofFixed32 = 7U;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(msg.oneofFixed32, 7U);
+ [orig release];
+ }
+
+ { // oneofFixed64
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofFixed64 = 8U;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(msg.oneofFixed64, 8U);
+ [orig release];
+ }
+
+ { // oneofSfixed32
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofSfixed32 = 9;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(msg.oneofSfixed32, 9);
+ [orig release];
+ }
+
+ { // oneofSfixed64
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofSfixed64 = 10;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(msg.oneofSfixed64, 10);
+ [orig release];
+ }
+
+ { // oneofFloat
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofFloat = 11.0f;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(msg.oneofFloat, 11.0f);
+ [orig release];
+ }
+
+ { // oneofDouble
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofDouble = 12.0;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(msg.oneofDouble, 12.0);
+ [orig release];
+ }
+
+ { // oneofBool
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofBool = NO;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBool);
+ XCTAssertEqual(msg.oneofBool, NO);
+ [orig release];
+ }
+
+ { // oneofString
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofString = @"foo";
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofString);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofString);
+ XCTAssertEqualObjects(msg.oneofString, @"foo");
+ [orig release];
+ }
+
+ { // oneofBytes
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
+ XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ [orig release];
+ }
+
+ { // oneofGroup
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofGroup = group;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofGroup);
+ XCTAssertEqualObjects(msg.oneofGroup, group);
+ [orig release];
+ }
+
+ { // oneofMessage
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofMessage = subMessage;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofMessage);
+ XCTAssertEqualObjects(msg.oneofMessage, subMessage);
+ [orig release];
+ }
+
+ { // oneofEnum
+ Message2 *orig = [[Message2 alloc] init];
+ orig.oneofEnum = Message2_Enum_Bar;
+ XCTAssertEqual(orig.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+ Message2 *msg = [Message2 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+ [orig release];
+ }
+
+ [group release];
+ [subMessage release];
+}
+
+//%PDDM-EXPAND TEST_ROUNDTRIP_ONEOFS(3, YES)
+// This block of code is generated, do not edit it directly.
+
+- (void)testProto3RoundTripOneof {
+
+ Message3 *subMessage = [[Message3 alloc] init];
+ XCTAssertNotNil(subMessage);
+ subMessage.optionalInt32 = 666;
+
+ { // oneofInt32
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofInt32 = 1;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt32);
+ XCTAssertEqual(msg.oneofInt32, 1);
+ [orig release];
+ }
+
+ { // oneofInt64
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofInt64 = 2;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofInt64);
+ XCTAssertEqual(msg.oneofInt64, 2);
+ [orig release];
+ }
+
+ { // oneofUint32
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofUint32 = 3U;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint32);
+ XCTAssertEqual(msg.oneofUint32, 3U);
+ [orig release];
+ }
+
+ { // oneofUint64
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofUint64 = 4U;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofUint64);
+ XCTAssertEqual(msg.oneofUint64, 4U);
+ [orig release];
+ }
+
+ { // oneofSint32
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofSint32 = 5;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint32);
+ XCTAssertEqual(msg.oneofSint32, 5);
+ [orig release];
+ }
+
+ { // oneofSint64
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofSint64 = 6;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSint64);
+ XCTAssertEqual(msg.oneofSint64, 6);
+ [orig release];
+ }
+
+ { // oneofFixed32
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofFixed32 = 7U;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed32);
+ XCTAssertEqual(msg.oneofFixed32, 7U);
+ [orig release];
+ }
+
+ { // oneofFixed64
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofFixed64 = 8U;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFixed64);
+ XCTAssertEqual(msg.oneofFixed64, 8U);
+ [orig release];
+ }
+
+ { // oneofSfixed32
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofSfixed32 = 9;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed32);
+ XCTAssertEqual(msg.oneofSfixed32, 9);
+ [orig release];
+ }
+
+ { // oneofSfixed64
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofSfixed64 = 10;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofSfixed64);
+ XCTAssertEqual(msg.oneofSfixed64, 10);
+ [orig release];
+ }
+
+ { // oneofFloat
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofFloat = 11.0f;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofFloat);
+ XCTAssertEqual(msg.oneofFloat, 11.0f);
+ [orig release];
+ }
+
+ { // oneofDouble
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofDouble = 12.0;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofDouble);
+ XCTAssertEqual(msg.oneofDouble, 12.0);
+ [orig release];
+ }
+
+ { // oneofBool
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofBool = YES;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBool);
+ XCTAssertEqual(msg.oneofBool, YES);
+ [orig release];
+ }
+
+ { // oneofString
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofString = @"foo";
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofString);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofString);
+ XCTAssertEqualObjects(msg.oneofString, @"foo");
+ [orig release];
+ }
+
+ { // oneofBytes
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
+ XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+ [orig release];
+ }
+
+ // Not "group" in proto3.
+
+ { // oneofMessage
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofMessage = subMessage;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofMessage);
+ XCTAssertEqualObjects(msg.oneofMessage, subMessage);
+ [orig release];
+ }
+
+ { // oneofEnum
+ Message3 *orig = [[Message3 alloc] init];
+ orig.oneofEnum = Message2_Enum_Bar;
+ XCTAssertEqual(orig.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+ Message3 *msg = [Message3 parseFromData:[orig data]];
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofEnum);
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
+ [orig release];
+ }
+
+ [subMessage release];
+}
+
+//%PDDM-EXPAND-END (2 expansions)
+
+#pragma mark - Subset from from map_tests.cc
+
+// TEST(GeneratedMapFieldTest, StandardWireFormat)
+- (void)testMap_StandardWireFormat {
+ NSData *data = DataFromCStr("\x0A\x04\x08\x01\x10\x01");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]);
+ XCTAssertEqual(val, 1);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, UnorderedWireFormat)
+- (void)testMap_UnorderedWireFormat {
+ // put value before key in wire format
+ NSData *data = DataFromCStr("\x0A\x04\x10\x01\x08\x02");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]);
+ XCTAssertEqual(val, 1);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, DuplicatedKeyWireFormat)
+- (void)testMap_DuplicatedKeyWireFormat {
+ // Two key fields in wire format
+ NSData *data = DataFromCStr("\x0A\x06\x08\x01\x08\x02\x10\x01");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]);
+ XCTAssertEqual(val, 1);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, DuplicatedValueWireFormat)
+- (void)testMap_DuplicatedValueWireFormat {
+ // Two value fields in wire format
+ NSData *data = DataFromCStr("\x0A\x06\x08\x01\x10\x01\x10\x02");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]);
+ XCTAssertEqual(val, 2);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, MissedKeyWireFormat)
+- (void)testMap_MissedKeyWireFormat {
+ // No key field in wire format
+ NSData *data = DataFromCStr("\x0A\x02\x10\x01");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:0 value:&val]);
+ XCTAssertEqual(val, 1);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, MissedValueWireFormat)
+- (void)testMap_MissedValueWireFormat {
+ // No value field in wire format
+ NSData *data = DataFromCStr("\x0A\x02\x08\x01");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:1 value:&val]);
+ XCTAssertEqual(val, 0);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, UnknownFieldWireFormat)
+- (void)testMap_UnknownFieldWireFormat {
+ // Unknown field in wire format
+ NSData *data = DataFromCStr("\x0A\x06\x08\x02\x10\x03\x18\x01");
+
+ TestMap *msg = [[TestMap alloc] initWithData:data];
+ XCTAssertEqual(msg.mapInt32Int32.count, 1U);
+ int32_t val = 666;
+ XCTAssertTrue([msg.mapInt32Int32 valueForKey:2 value:&val]);
+ XCTAssertEqual(val, 3);
+
+ [msg release];
+}
+
+// TEST(GeneratedMapFieldTest, CorruptedWireFormat)
+- (void)testMap_CorruptedWireFormat {
+ // corrupted data in wire format
+ NSData *data = DataFromCStr("\x0A\x06\x08\x02\x11\x03");
+
+ XCTAssertThrowsSpecificNamed([TestMap parseFromData:data], NSException,
+ NSParseErrorException);
+}
+
+// TEST(GeneratedMapFieldTest, Proto2UnknownEnum)
+- (void)testMap_Proto2UnknownEnum {
+ TestEnumMapPlusExtra *orig = [[TestEnumMapPlusExtra alloc] init];
+
+ orig.knownMapField = [GPBInt32EnumDictionary
+ dictionaryWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue];
+ orig.unknownMapField = [GPBInt32EnumDictionary
+ dictionaryWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue];
+ [orig.knownMapField setValue:Proto2MapEnumPlusExtra_EProto2MapEnumFoo
+ forKey:0];
+ [orig.unknownMapField setValue:Proto2MapEnumPlusExtra_EProto2MapEnumExtra
+ forKey:0];
+
+ TestEnumMap *msg1 = [TestEnumMap parseFromData:[orig data]];
+ XCTAssertEqual(msg1.knownMapField.count, 1U);
+ int32_t val = -1;
+ XCTAssertTrue([msg1.knownMapField valueForKey:0 value:&val]);
+ XCTAssertEqual(val, Proto2MapEnum_Proto2MapEnumFoo);
+ XCTAssertEqual(msg1.unknownFields.countOfFields, 1U);
+
+ TestEnumMapPlusExtra *msg2 = [TestEnumMapPlusExtra parseFromData:[msg1 data]];
+ val = -1;
+ XCTAssertEqual(msg2.knownMapField.count, 1U);
+ XCTAssertTrue([msg2.knownMapField valueForKey:0 value:&val]);
+ XCTAssertEqual(val, Proto2MapEnumPlusExtra_EProto2MapEnumFoo);
+ val = -1;
+ XCTAssertEqual(msg2.unknownMapField.count, 1U);
+ XCTAssertTrue([msg2.unknownMapField valueForKey:0 value:&val]);
+ XCTAssertEqual(val, Proto2MapEnumPlusExtra_EProto2MapEnumExtra);
+ XCTAssertEqual(msg2.unknownFields.countOfFields, 0U);
+
+ XCTAssertEqualObjects(orig, msg2);
+
+ [orig release];
+}
+
+#pragma mark -
+
+@end
diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m
new file mode 100644
index 00000000..5ec67cd9
--- /dev/null
+++ b/objectivec/Tests/GPBMessageTests.m
@@ -0,0 +1,1728 @@
+// 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 "GPBTestUtilities.h"
+
+#import <objc/runtime.h>
+
+#import "GPBArray_PackagePrivate.h"
+#import "GPBDescriptor.h"
+#import "GPBField_PackagePrivate.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+#import "google/protobuf/UnittestNameMangling.pbobjc.h"
+
+@interface MessageTests : GPBTestCase
+@end
+
+@implementation MessageTests
+
+// TODO(thomasvl): this should get split into a few files of logic junks, it is
+// a jumble
+// of things at the moment (and the testutils have a bunch of the real
+// assertions).
+
+#ifdef DEBUG
+- (void)assertBlock:(void (^)())block
+ throwsWithMessageInUserInfo:(GPBMessage *)message {
+ @try {
+ block();
+ XCTAssertTrue(NO);
+ }
+ @catch (NSException *e) {
+ XCTAssertEqualObjects([e userInfo][GPBExceptionMessageKey], message);
+ }
+}
+#endif // DEBUG
+
+- (TestAllTypes *)mergeSource {
+ TestAllTypes *message = [TestAllTypes message];
+ [message setOptionalInt32:1];
+ [message setOptionalString:@"foo"];
+ [message setOptionalForeignMessage:[ForeignMessage message]];
+ message.repeatedStringArray = [NSMutableArray array];
+ [message.repeatedStringArray addObject:@"bar"];
+ return message;
+}
+
+- (TestAllTypes *)mergeDestination {
+ TestAllTypes *message = [TestAllTypes message];
+ [message setOptionalInt64:2];
+ [message setOptionalString:@"baz"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setC:3];
+ [message setOptionalForeignMessage:foreignMessage];
+ message.repeatedStringArray = [NSMutableArray array];
+ [message.repeatedStringArray addObject:@"qux"];
+ return message;
+}
+
+- (TestAllTypes *)mergeDestinationWithoutForeignMessageIvar {
+ TestAllTypes *message = [TestAllTypes message];
+ [message setOptionalInt64:2];
+ [message setOptionalString:@"baz"];
+ message.repeatedStringArray = [NSMutableArray array];
+ [message.repeatedStringArray addObject:@"qux"];
+ return message;
+}
+
+- (TestAllTypes *)mergeResult {
+ TestAllTypes *message = [TestAllTypes message];
+ [message setOptionalInt32:1];
+ [message setOptionalInt64:2];
+ [message setOptionalString:@"foo"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setC:3];
+ [message setOptionalForeignMessage:foreignMessage];
+ message.repeatedStringArray = [NSMutableArray array];
+ [message.repeatedStringArray addObject:@"qux"];
+ [message.repeatedStringArray addObject:@"bar"];
+ return message;
+}
+
+- (TestAllTypes *)mergeResultForDestinationWithoutForeignMessageIvar {
+ TestAllTypes *message = [TestAllTypes message];
+ [message setOptionalInt32:1];
+ [message setOptionalInt64:2];
+ [message setOptionalString:@"foo"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [message setOptionalForeignMessage:foreignMessage];
+ message.repeatedStringArray = [NSMutableArray array];
+ [message.repeatedStringArray addObject:@"qux"];
+ [message.repeatedStringArray addObject:@"bar"];
+ return message;
+}
+
+- (TestAllExtensions *)mergeExtensionsDestination {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [message setExtension:[UnittestRoot optionalInt32Extension] value:@5];
+ [message setExtension:[UnittestRoot optionalStringExtension] value:@"foo"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ foreignMessage.c = 4;
+ [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+ value:foreignMessage];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+ value:nestedMessage];
+ return message;
+}
+
+- (TestAllExtensions *)mergeExtensionsSource {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [message setExtension:[UnittestRoot optionalInt64Extension] value:@6];
+ [message setExtension:[UnittestRoot optionalStringExtension] value:@"bar"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+ value:foreignMessage];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ nestedMessage.bb = 7;
+ [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+ value:nestedMessage];
+ return message;
+}
+
+- (TestAllExtensions *)mergeExtensionsResult {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [message setExtension:[UnittestRoot optionalInt32Extension] value:@5];
+ [message setExtension:[UnittestRoot optionalInt64Extension] value:@6];
+ [message setExtension:[UnittestRoot optionalStringExtension] value:@"bar"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ foreignMessage.c = 4;
+ [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+ value:foreignMessage];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ nestedMessage.bb = 7;
+ [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+ value:nestedMessage];
+ return message;
+}
+
+- (void)testMergeFrom {
+ TestAllTypes *result = [[self.mergeDestination copy] autorelease];
+ [result mergeFrom:self.mergeSource];
+ NSData *resultData = [result data];
+ NSData *mergeResultData = [self.mergeResult data];
+ XCTAssertEqualObjects(resultData, mergeResultData);
+ XCTAssertEqualObjects(result, self.mergeResult);
+
+ // Test when destination does not have an Ivar (type is an object) but source
+ // has such Ivar.
+ // The result must has the Ivar which is same as the one in source.
+ result = [[self.mergeDestinationWithoutForeignMessageIvar copy] autorelease];
+ [result mergeFrom:self.mergeSource];
+ resultData = [result data];
+ mergeResultData =
+ [self.mergeResultForDestinationWithoutForeignMessageIvar data];
+ XCTAssertEqualObjects(resultData, mergeResultData);
+ XCTAssertEqualObjects(
+ result, self.mergeResultForDestinationWithoutForeignMessageIvar);
+
+ // Test when destination is empty.
+ // The result must is same as the source.
+ result = [TestAllTypes message];
+ [result mergeFrom:self.mergeSource];
+ resultData = [result data];
+ mergeResultData = [self.mergeSource data];
+ XCTAssertEqualObjects(resultData, mergeResultData);
+ XCTAssertEqualObjects(result, self.mergeSource);
+}
+
+- (void)testMergeFromWithExtensions {
+ TestAllExtensions *result = [self mergeExtensionsDestination];
+ [result mergeFrom:[self mergeExtensionsSource]];
+ NSData *resultData = [result data];
+ NSData *mergeResultData = [[self mergeExtensionsResult] data];
+ XCTAssertEqualObjects(resultData, mergeResultData);
+ XCTAssertEqualObjects(result, [self mergeExtensionsResult]);
+
+ // Test merging from data.
+ result = [self mergeExtensionsDestination];
+ [result mergeFromData:[[self mergeExtensionsSource] data]
+ extensionRegistry:[UnittestRoot extensionRegistry]];
+ resultData = [result data];
+ XCTAssertEqualObjects(resultData, mergeResultData);
+ XCTAssertEqualObjects(result, [self mergeExtensionsResult]);
+}
+
+- (void)testIsEquals {
+ TestAllTypes *result = [[self.mergeDestination copy] autorelease];
+ [result mergeFrom:self.mergeSource];
+ XCTAssertEqualObjects(result.data, self.mergeResult.data);
+ XCTAssertEqualObjects(result, self.mergeResult);
+ TestAllTypes *result2 = [[self.mergeDestination copy] autorelease];
+ XCTAssertNotEqualObjects(result2.data, self.mergeResult.data);
+ XCTAssertNotEqualObjects(result2, self.mergeResult);
+}
+
+// =================================================================
+// Required-field-related tests.
+
+- (TestRequired *)testRequiredInitialized {
+ TestRequired *message = [TestRequired message];
+ [message setA:1];
+ [message setB:2];
+ [message setC:3];
+ return message;
+}
+
+- (void)testRequired {
+ TestRequired *message = [TestRequired message];
+
+ XCTAssertFalse(message.initialized);
+ [message setA:1];
+ XCTAssertFalse(message.initialized);
+ [message setB:1];
+ XCTAssertFalse(message.initialized);
+ [message setC:1];
+ XCTAssertTrue(message.initialized);
+}
+
+- (void)testRequiredForeign {
+ TestRequiredForeign *message = [TestRequiredForeign message];
+
+ XCTAssertTrue(message.initialized);
+
+ [message setOptionalMessage:[TestRequired message]];
+ XCTAssertFalse(message.initialized);
+
+ [message setOptionalMessage:self.testRequiredInitialized];
+ XCTAssertTrue(message.initialized);
+
+ message.repeatedMessageArray = [NSMutableArray array];
+ [message.repeatedMessageArray addObject:[TestRequired message]];
+ XCTAssertFalse(message.initialized);
+
+ [message.repeatedMessageArray removeAllObjects];
+ [message.repeatedMessageArray addObject:self.testRequiredInitialized];
+ XCTAssertTrue(message.initialized);
+}
+
+- (void)testRequiredExtension {
+ TestAllExtensions *message = [TestAllExtensions message];
+
+ XCTAssertTrue(message.initialized);
+
+ [message setExtension:[TestRequired single] value:[TestRequired message]];
+ XCTAssertFalse(message.initialized);
+
+ [message setExtension:[TestRequired single]
+ value:self.testRequiredInitialized];
+ XCTAssertTrue(message.initialized);
+
+ [message addExtension:[TestRequired multi] value:[TestRequired message]];
+ XCTAssertFalse(message.initialized);
+
+ [message setExtension:[TestRequired multi]
+ index:0
+ value:self.testRequiredInitialized];
+ XCTAssertTrue(message.initialized);
+}
+
+#ifdef DEBUG
+- (void)testUninitializedException {
+ TestRequired *message = [TestRequired message];
+ [self assertBlock:^{
+ [message data];
+ } throwsWithMessageInUserInfo:message];
+}
+#endif // DEBUG
+
+- (void)testInitialized {
+ // We're mostly testing that no exception is thrown.
+ TestRequired *message = [TestRequired message];
+ XCTAssertFalse(message.initialized);
+}
+
+#ifdef DEBUG
+- (void)testNestedUninitializedException {
+ TestRequiredForeign *message = [TestRequiredForeign message];
+ [message setOptionalMessage:[TestRequired message]];
+ message.repeatedMessageArray = [NSMutableArray array];
+ [message.repeatedMessageArray addObject:[TestRequired message]];
+ [message.repeatedMessageArray addObject:[TestRequired message]];
+ [self assertBlock:^{
+ [message data];
+ } throwsWithMessageInUserInfo:message];
+}
+#endif // DEBUG
+
+- (void)testNestedInitialized {
+ // We're mostly testing that no exception is thrown.
+
+ TestRequiredForeign *message = [TestRequiredForeign message];
+ [message setOptionalMessage:[TestRequired message]];
+ message.repeatedMessageArray = [NSMutableArray array];
+ [message.repeatedMessageArray addObject:[TestRequired message]];
+ [message.repeatedMessageArray addObject:[TestRequired message]];
+
+ XCTAssertFalse(message.initialized);
+}
+
+#ifdef DEBUG
+- (void)testParseUninitialized {
+ [self assertBlock:^{
+ [TestRequired parseFromData:GPBEmptyNSData()];
+ } throwsWithMessageInUserInfo:[TestRequired message]];
+}
+#endif // DEBUG
+
+- (void)testCoding {
+ NSData *data =
+ [NSKeyedArchiver archivedDataWithRootObject:[self mergeResult]];
+ id unarchivedObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
+
+ XCTAssertEqualObjects(unarchivedObject, [self mergeResult]);
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(unarchivedObject, [self mergeResult]);
+}
+
+- (void)testObjectReset {
+ // Tests a failure where clearing out defaults values caused an over release.
+ TestAllTypes *message = [TestAllTypes message];
+ message.hasOptionalNestedMessage = NO;
+ [message setOptionalNestedMessage:[TestAllTypes_NestedMessage message]];
+ message.hasOptionalNestedMessage = NO;
+ [message setOptionalNestedMessage:[TestAllTypes_NestedMessage message]];
+ [message setOptionalNestedMessage:nil];
+ message.hasOptionalNestedMessage = NO;
+}
+
+- (void)testSettingHasToYes {
+ TestAllTypes *message = [TestAllTypes message];
+ XCTAssertThrows([message setHasOptionalNestedMessage:YES]);
+}
+
+- (void)testRoot {
+ XCTAssertNotNil([UnittestRoot extensionRegistry]);
+}
+
+- (void)testGPBMessageSize {
+ // See the note in GPBMessage_PackagePrivate.h about why we want to keep the
+ // base instance size pointer size aligned.
+ size_t messageSize = class_getInstanceSize([GPBMessage class]);
+ XCTAssertEqual((messageSize % sizeof(void *)), (size_t)0,
+ @"Base size isn't pointer size aligned");
+
+ // Since we add storage ourselves (see +allocWithZone: in GPBMessage), confirm
+ // that the size of some generated classes is still the same as the base for
+ // that logic to work as desired.
+ size_t testMessageSize = class_getInstanceSize([TestAllTypes class]);
+ XCTAssertEqual(testMessageSize, messageSize);
+}
+
+- (void)testInit {
+ TestAllTypes *message = [TestAllTypes message];
+ [self assertClear:message];
+}
+
+- (void)testAccessors {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [self assertAllFieldsSet:message repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testKVC_ValueForKey {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [self assertAllFieldsKVCMatch:message];
+}
+
+- (void)testKVC_SetValue_ForKey {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFieldsViaKVC:message repeatedCount:kGPBDefaultRepeatCount];
+ [self assertAllFieldsKVCMatch:message];
+ [self assertAllFieldsSet:message repeatedCount:kGPBDefaultRepeatCount];
+ [self assertAllFieldsKVCMatch:message];
+}
+
+- (void)testDescription {
+ // No real test, just exercise code
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+
+ GPBUnknownFieldSet *unknownFields =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ GPBField *field = [[[GPBField alloc] initWithNumber:2] autorelease];
+ [field addVarint:2];
+ [unknownFields addField:field];
+ field = [[[GPBField alloc] initWithNumber:3] autorelease];
+ [field addVarint:4];
+ [unknownFields addField:field];
+
+ [message setUnknownFields:unknownFields];
+
+ NSString *description = [message description];
+ XCTAssertGreaterThan([description length], 0U);
+
+ GPBMessage *message2 = [TestAllExtensions message];
+ [message2 setExtension:[UnittestRoot optionalInt32Extension] value:@1];
+
+ [message2 addExtension:[UnittestRoot repeatedInt32Extension] value:@2];
+
+ description = [message2 description];
+ XCTAssertGreaterThan([description length], 0U);
+}
+
+- (void)testSetter {
+ // Test to make sure that if we set a value that has a default value
+ // with the default, that the has is set, and the value gets put into the
+ // message correctly.
+ TestAllTypes *message = [TestAllTypes message];
+ GPBDescriptor *descriptor = [[message class] descriptor];
+ XCTAssertNotNil(descriptor);
+ GPBFieldDescriptor *fieldDescriptor =
+ [descriptor fieldWithName:@"defaultInt32"];
+ XCTAssertNotNil(fieldDescriptor);
+ GPBValue defaultValue = [fieldDescriptor defaultValue];
+ [message setDefaultInt32:defaultValue.valueInt32];
+ XCTAssertTrue(message.hasDefaultInt32);
+ XCTAssertEqual(message.defaultInt32, defaultValue.valueInt32);
+
+ // Do the same thing with an object type.
+ message = [TestAllTypes message];
+ fieldDescriptor = [descriptor fieldWithName:@"defaultString"];
+ XCTAssertNotNil(fieldDescriptor);
+ defaultValue = [fieldDescriptor defaultValue];
+ [message setDefaultString:defaultValue.valueString];
+ XCTAssertTrue(message.hasDefaultString);
+ XCTAssertEqualObjects(message.defaultString, defaultValue.valueString);
+
+ // Test default string type.
+ message = [TestAllTypes message];
+ XCTAssertEqualObjects(message.defaultString, @"hello");
+ XCTAssertFalse(message.hasDefaultString);
+ fieldDescriptor = [descriptor fieldWithName:@"defaultString"];
+ XCTAssertNotNil(fieldDescriptor);
+ defaultValue = [fieldDescriptor defaultValue];
+ [message setDefaultString:defaultValue.valueString];
+ XCTAssertEqualObjects(message.defaultString, @"hello");
+ XCTAssertTrue(message.hasDefaultString);
+ [message setDefaultString:nil];
+ XCTAssertEqualObjects(message.defaultString, @"hello");
+ XCTAssertFalse(message.hasDefaultString);
+ message.hasDefaultString = NO;
+ XCTAssertFalse(message.hasDefaultString);
+ XCTAssertEqualObjects(message.defaultString, @"hello");
+
+ // Test default bytes type.
+ NSData *defaultBytes = [@"world" dataUsingEncoding:NSUTF8StringEncoding];
+ XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+ XCTAssertFalse(message.hasDefaultString);
+ fieldDescriptor = [descriptor fieldWithName:@"defaultBytes"];
+ XCTAssertNotNil(fieldDescriptor);
+ defaultValue = [fieldDescriptor defaultValue];
+ [message setDefaultBytes:defaultValue.valueData];
+ XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+ XCTAssertTrue(message.hasDefaultBytes);
+ [message setDefaultBytes:nil];
+ XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+ XCTAssertFalse(message.hasDefaultBytes);
+ message.hasDefaultBytes = NO;
+ XCTAssertFalse(message.hasDefaultBytes);
+ XCTAssertEqualObjects(message.defaultBytes, defaultBytes);
+
+ // Test optional string.
+ XCTAssertFalse(message.hasOptionalString);
+ XCTAssertEqualObjects(message.optionalString, @"");
+ XCTAssertFalse(message.hasOptionalString);
+ message.optionalString = nil;
+ XCTAssertFalse(message.hasOptionalString);
+ XCTAssertEqualObjects(message.optionalString, @"");
+ NSString *string = @"string";
+ message.optionalString = string;
+ XCTAssertEqualObjects(message.optionalString, string);
+ XCTAssertTrue(message.hasOptionalString);
+ message.optionalString = nil;
+ XCTAssertFalse(message.hasOptionalString);
+ XCTAssertEqualObjects(message.optionalString, @"");
+
+ // Test optional data.
+ XCTAssertFalse(message.hasOptionalBytes);
+ XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+ XCTAssertFalse(message.hasOptionalBytes);
+ message.optionalBytes = nil;
+ XCTAssertFalse(message.hasOptionalBytes);
+ XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+ NSData *data = [@"bytes" dataUsingEncoding:NSUTF8StringEncoding];
+ message.optionalBytes = data;
+ XCTAssertEqualObjects(message.optionalBytes, data);
+ XCTAssertTrue(message.hasOptionalBytes);
+ message.optionalBytes = nil;
+ XCTAssertFalse(message.hasOptionalBytes);
+ XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+
+ // Test lazy message setting
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ XCTAssertNotNil(message.optionalLazyMessage);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ message.hasOptionalLazyMessage = NO;
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ XCTAssertNotNil(message.optionalLazyMessage);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ message.optionalLazyMessage = nil;
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+
+ // Test nested messages
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ message.optionalLazyMessage.bb = 1;
+ XCTAssertTrue(message.hasOptionalLazyMessage);
+ XCTAssertEqual(message.optionalLazyMessage.bb, 1);
+ XCTAssertNotNil(message.optionalLazyMessage);
+ message.optionalLazyMessage = nil;
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ XCTAssertEqual(message.optionalLazyMessage.bb, 0);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+ XCTAssertNotNil(message.optionalLazyMessage);
+
+ // -testDefaultSubMessages tests the "defaulting" handling of fields
+ // containing messages.
+}
+
+- (void)testRepeatedSetters {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [self modifyRepeatedFields:message];
+ [self assertRepeatedFieldsModified:message
+ repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testClear {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [self clearAllFields:message];
+ [self assertClear:message];
+ TestAllTypes *message2 = [TestAllTypes message];
+ XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testClearKVC {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
+ [self clearAllFields:message];
+ [self assertClear:message];
+ [self assertClearKVC:message];
+}
+
+- (void)testClearExtension {
+ // clearExtension() is not actually used in TestUtil, so try it manually.
+ GPBMessage *message1 = [TestAllExtensions message];
+ [message1 setExtension:[UnittestRoot optionalInt32Extension] value:@1];
+
+ XCTAssertTrue([message1 hasExtension:[UnittestRoot optionalInt32Extension]]);
+ [message1 clearExtension:[UnittestRoot optionalInt32Extension]];
+ XCTAssertFalse([message1 hasExtension:[UnittestRoot optionalInt32Extension]]);
+
+ GPBMessage *message2 = [TestAllExtensions message];
+ [message2 addExtension:[UnittestRoot repeatedInt32Extension] value:@1];
+
+ XCTAssertEqual(
+ [[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count],
+ (NSUInteger)1);
+ [message2 clearExtension:[UnittestRoot repeatedInt32Extension]];
+ XCTAssertEqual(
+ [[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count],
+ (NSUInteger)0);
+
+ // Clearing an unset extension field shouldn't make the target message
+ // visible.
+ GPBMessage *message3 = [TestAllExtensions message];
+ GPBMessage *extension_msg =
+ [message3 getExtension:[UnittestObjcRoot recursiveExtension]];
+ XCTAssertFalse([message3 hasExtension:[UnittestObjcRoot recursiveExtension]]);
+ [extension_msg clearExtension:[UnittestRoot optionalInt32Extension]];
+ XCTAssertFalse([message3 hasExtension:[UnittestObjcRoot recursiveExtension]]);
+}
+
+- (void)testDefaultingSubMessages {
+ TestAllTypes *message = [TestAllTypes message];
+
+ // Initially they should all not have values.
+
+ XCTAssertFalse(message.hasOptionalGroup);
+ XCTAssertFalse(message.hasOptionalNestedMessage);
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ XCTAssertFalse(message.hasOptionalImportMessage);
+ XCTAssertFalse(message.hasOptionalPublicImportMessage);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+
+ // They should auto create something when fetched.
+
+ TestAllTypes_OptionalGroup *optionalGroup = [message.optionalGroup retain];
+ TestAllTypes_NestedMessage *optionalNestedMessage =
+ [message.optionalNestedMessage retain];
+ ForeignMessage *optionalForeignMessage =
+ [message.optionalForeignMessage retain];
+ ImportMessage *optionalImportMessage = [message.optionalImportMessage retain];
+ PublicImportMessage *optionalPublicImportMessage =
+ [message.optionalPublicImportMessage retain];
+ TestAllTypes_NestedMessage *optionalLazyMessage =
+ [message.optionalLazyMessage retain];
+
+ XCTAssertNotNil(optionalGroup);
+ XCTAssertNotNil(optionalNestedMessage);
+ XCTAssertNotNil(optionalForeignMessage);
+ XCTAssertNotNil(optionalImportMessage);
+ XCTAssertNotNil(optionalPublicImportMessage);
+ XCTAssertNotNil(optionalLazyMessage);
+
+ // Although they were created, they should not respond to hasValue until that
+ // submessage is mutated.
+
+ XCTAssertFalse(message.hasOptionalGroup);
+ XCTAssertFalse(message.hasOptionalNestedMessage);
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ XCTAssertFalse(message.hasOptionalImportMessage);
+ XCTAssertFalse(message.hasOptionalPublicImportMessage);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+
+ // And they set that value back in to the message since the value created was
+ // mutable (so a second fetch should give the same object).
+
+ XCTAssertEqual(message.optionalGroup, optionalGroup);
+ XCTAssertEqual(message.optionalNestedMessage, optionalNestedMessage);
+ XCTAssertEqual(message.optionalForeignMessage, optionalForeignMessage);
+ XCTAssertEqual(message.optionalImportMessage, optionalImportMessage);
+ XCTAssertEqual(message.optionalPublicImportMessage,
+ optionalPublicImportMessage);
+ XCTAssertEqual(message.optionalLazyMessage, optionalLazyMessage);
+
+ // And the default objects for a second message should be distinct (again,
+ // since they are mutable, each needs their own copy).
+
+ TestAllTypes *message2 = [TestAllTypes message];
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(message2.optionalGroup, optionalGroup);
+ XCTAssertNotEqual(message2.optionalNestedMessage, optionalNestedMessage);
+ XCTAssertNotEqual(message2.optionalForeignMessage, optionalForeignMessage);
+ XCTAssertNotEqual(message2.optionalImportMessage, optionalImportMessage);
+ XCTAssertNotEqual(message2.optionalPublicImportMessage,
+ optionalPublicImportMessage);
+ XCTAssertNotEqual(message2.optionalLazyMessage, optionalLazyMessage);
+
+ // Setting the values to nil will clear the has flag, and on next access you
+ // get back new submessages.
+
+ message.optionalGroup = nil;
+ message.optionalNestedMessage = nil;
+ message.optionalForeignMessage = nil;
+ message.optionalImportMessage = nil;
+ message.optionalPublicImportMessage = nil;
+ message.optionalLazyMessage = nil;
+
+ XCTAssertFalse(message.hasOptionalGroup);
+ XCTAssertFalse(message.hasOptionalNestedMessage);
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ XCTAssertFalse(message.hasOptionalImportMessage);
+ XCTAssertFalse(message.hasOptionalPublicImportMessage);
+ XCTAssertFalse(message.hasOptionalLazyMessage);
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(message.optionalGroup, optionalGroup);
+ XCTAssertNotEqual(message.optionalNestedMessage, optionalNestedMessage);
+ XCTAssertNotEqual(message.optionalForeignMessage, optionalForeignMessage);
+ XCTAssertNotEqual(message.optionalImportMessage, optionalImportMessage);
+ XCTAssertNotEqual(message.optionalPublicImportMessage,
+ optionalPublicImportMessage);
+ XCTAssertNotEqual(message.optionalLazyMessage, optionalLazyMessage);
+
+ [optionalGroup release];
+ [optionalNestedMessage release];
+ [optionalForeignMessage release];
+ [optionalImportMessage release];
+ [optionalPublicImportMessage release];
+ [optionalLazyMessage release];
+}
+
+- (void)testMultiplePointersToAutocreatedMessage {
+ // Multiple objects pointing to the same autocreated message.
+ TestAllTypes *message = [TestAllTypes message];
+ TestAllTypes *message2 = [TestAllTypes message];
+ message2.optionalGroup = message.optionalGroup;
+ XCTAssertTrue([message2 hasOptionalGroup]);
+ XCTAssertFalse([message hasOptionalGroup]);
+ message2.optionalGroup.a = 42;
+ XCTAssertTrue([message hasOptionalGroup]);
+ XCTAssertTrue([message2 hasOptionalGroup]);
+}
+
+- (void)testCopyWithAutocreatedMessage {
+ // Mutable copy should not copy autocreated messages.
+ TestAllTypes *message = [TestAllTypes message];
+ message.optionalGroup.a = 42;
+ XCTAssertNotNil(message.optionalNestedMessage);
+ TestAllTypes *message2 = [[message copy] autorelease];
+ XCTAssertTrue([message2 hasOptionalGroup]);
+ XCTAssertFalse([message2 hasOptionalNestedMessage]);
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(message.optionalNestedMessage,
+ message2.optionalNestedMessage);
+}
+
+- (void)testClearAutocreatedSubmessage {
+ // Call clear on an intermediate submessage should cause it to get recreated
+ // on the next call.
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ TestRecursiveMessage *message_inner = [message.a.a.a retain];
+ XCTAssertNotNil(message_inner);
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(message_inner, message.a.a));
+ [message.a.a clear];
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(message_inner, message.a.a));
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(message.a.a.a, message_inner);
+ [message_inner release];
+}
+
+- (void)testRetainAutocreatedSubmessage {
+ // Should be able to retain autocreated submessage while the creator is
+ // dealloced.
+ TestAllTypes *message = [TestAllTypes message];
+
+ ForeignMessage *subMessage;
+ @autoreleasepool {
+ TestAllTypes *message2 = [TestAllTypes message];
+ subMessage = message2.optionalForeignMessage; // Autocreated
+ message.optionalForeignMessage = subMessage;
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(message.optionalForeignMessage,
+ message2));
+ }
+
+ // Should be the same object, and should still be live.
+ XCTAssertEqual(message.optionalForeignMessage, subMessage);
+ XCTAssertNotNil([subMessage description]);
+}
+
+- (void)testSetNilAutocreatedSubmessage {
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ TestRecursiveMessage *message_inner = [message.a.a retain];
+ XCTAssertFalse([message hasA]);
+ XCTAssertFalse([message.a hasA]);
+ message.a.a = nil;
+
+ // |message.a| has to be made visible, but |message.a.a| was set to nil so
+ // shouldn't be.
+ XCTAssertTrue([message hasA]);
+ XCTAssertFalse([message.a hasA]);
+
+ // Setting submessage to nil should cause it to lose its creator.
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(message_inner, message.a));
+
+ // After setting to nil, getting it again should create a new autocreated
+ // message.
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(message.a.a, message_inner);
+
+ [message_inner release];
+}
+
+- (void)testSetDoesntHaveAutocreatedSubmessage {
+ // Clearing submessage (set has == NO) should NOT cause it to lose its
+ // creator.
+ TestAllTypes *message = [TestAllTypes message];
+ TestAllTypes_NestedMessage *nestedMessage = message.optionalNestedMessage;
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+ [message setHasOptionalNestedMessage:NO];
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+ XCTAssertEqual(message.optionalNestedMessage, nestedMessage);
+}
+
+- (void)testSetAutocreatedMessageBecomesVisible {
+ // Setting a value should cause the submessage to appear to its creator.
+ // Test this several levels deep.
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ message.a.a.a.a.i = 42;
+ XCTAssertTrue([message hasA]);
+ XCTAssertTrue([message.a hasA]);
+ XCTAssertTrue([message.a.a hasA]);
+ XCTAssertTrue([message.a.a.a hasA]);
+ XCTAssertFalse([message.a.a.a.a hasA]);
+ XCTAssertEqual(message.a.a.a.a.i, 42);
+}
+
+- (void)testClearUnsetFieldOfAutocreatedMessage {
+ // Clearing an unset field should not cause the submessage to appear to its
+ // creator.
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ message.a.a.a.a.hasI = NO;
+ XCTAssertFalse([message hasA]);
+ XCTAssertFalse([message.a hasA]);
+ XCTAssertFalse([message.a.a hasA]);
+ XCTAssertFalse([message.a.a.a hasA]);
+}
+
+- (void)testAutocreatedSubmessageAssignSkip {
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ TestRecursiveMessage *messageLevel1 = [message.a retain];
+ TestRecursiveMessage *messageLevel2 = [message.a.a retain];
+ TestRecursiveMessage *messageLevel3 = [message.a.a.a retain];
+ TestRecursiveMessage *messageLevel4 = [message.a.a.a.a retain];
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel1, message));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel4, messageLevel3));
+
+ // Test skipping over an autocreated submessage and ensure it gets unset.
+ message.a = message.a.a;
+ XCTAssertEqual(message.a, messageLevel2);
+ XCTAssertTrue([message hasA]);
+ XCTAssertEqual(message.a.a, messageLevel3);
+ XCTAssertFalse([message.a hasA]);
+ XCTAssertEqual(message.a.a.a, messageLevel4);
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel1,
+ message)); // Because it was orphaned.
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2));
+
+ [messageLevel1 release];
+ [messageLevel2 release];
+ [messageLevel3 release];
+ [messageLevel4 release];
+}
+
+- (void)testAutocreatedSubmessageAssignLoop {
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ TestRecursiveMessage *messageLevel1 = [message.a retain];
+ TestRecursiveMessage *messageLevel2 = [message.a.a retain];
+ TestRecursiveMessage *messageLevel3 = [message.a.a.a retain];
+ TestRecursiveMessage *messageLevel4 = [message.a.a.a.a retain];
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel1, message));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel2, messageLevel1));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel3, messageLevel2));
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(messageLevel4, messageLevel3));
+
+ // Test a property with a loop. You'd never do this but at least ensure the
+ // autocreated submessages behave sanely.
+ message.a.a = message.a;
+ XCTAssertTrue([message hasA]);
+ XCTAssertEqual(message.a, messageLevel1);
+ XCTAssertTrue([message.a hasA]);
+ XCTAssertEqual(message.a.a, messageLevel1);
+ XCTAssertTrue([message.a.a hasA]);
+ XCTAssertEqual(message.a.a.a, messageLevel1);
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel1,
+ message)); // Because it was assigned.
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(messageLevel2,
+ messageLevel1)); // Because it was orphaned.
+ XCTAssertFalse([messageLevel2 hasA]);
+
+ // Break the retain loop.
+ message.a.a = nil;
+ XCTAssertTrue([message hasA]);
+ XCTAssertFalse([message.a hasA]);
+
+ [messageLevel1 release];
+ [messageLevel2 release];
+ [messageLevel3 release];
+ [messageLevel4 release];
+}
+
+- (void)testSetAutocreatedSubmessage {
+ // Setting autocreated submessage to another value should cause the old one to
+ // lose its creator.
+ TestAllTypes *message = [TestAllTypes message];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [message.optionalNestedMessage retain];
+
+ message.optionalNestedMessage = [TestAllTypes_NestedMessage message];
+ XCTAssertTrue([message hasOptionalNestedMessage]);
+ XCTAssertTrue(message.optionalNestedMessage != nestedMessage);
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(nestedMessage, message));
+
+ [nestedMessage release];
+}
+
+- (void)testAutocreatedUnknownFields {
+ // Doing anything with (except reading) unknown fields should cause the
+ // submessage to become visible.
+ TestAllTypes *message = [TestAllTypes message];
+ XCTAssertNotNil(message.optionalNestedMessage);
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+ XCTAssertNil(message.optionalNestedMessage.unknownFields);
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+
+ GPBUnknownFieldSet *unknownFields =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ message.optionalNestedMessage.unknownFields = unknownFields;
+ XCTAssertTrue([message hasOptionalNestedMessage]);
+
+ message.optionalNestedMessage = nil;
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+ [message.optionalNestedMessage setUnknownFields:unknownFields];
+ XCTAssertTrue([message hasOptionalNestedMessage]);
+}
+
+- (void)testSetAutocreatedSubmessageToSelf {
+ // Setting submessage to itself should cause it to become visible.
+ TestAllTypes *message = [TestAllTypes message];
+ XCTAssertNotNil(message.optionalNestedMessage);
+ XCTAssertFalse([message hasOptionalNestedMessage]);
+ message.optionalNestedMessage = message.optionalNestedMessage;
+ XCTAssertTrue([message hasOptionalNestedMessage]);
+}
+
+- (void)testAutocreatedSubmessageMemoryLeaks {
+ // Test for memory leaks with autocreated submessages.
+ TestRecursiveMessage *message;
+ TestRecursiveMessage *messageLevel1;
+ TestRecursiveMessage *messageLevel2;
+ TestRecursiveMessage *messageLevel3;
+ TestRecursiveMessage *messageLevel4;
+ @autoreleasepool {
+ message = [[TestRecursiveMessage alloc] init];
+ messageLevel1 = [message.a retain];
+ messageLevel2 = [message.a.a retain];
+ messageLevel3 = [message.a.a.a retain];
+ messageLevel4 = [message.a.a.a.a retain];
+ message.a.i = 1;
+ }
+
+ XCTAssertEqual(message.retainCount, (NSUInteger)1);
+ [message release];
+ XCTAssertEqual(messageLevel1.retainCount, (NSUInteger)1);
+ [messageLevel1 release];
+ XCTAssertEqual(messageLevel2.retainCount, (NSUInteger)1);
+ [messageLevel2 release];
+ XCTAssertEqual(messageLevel3.retainCount, (NSUInteger)1);
+ [messageLevel3 release];
+ XCTAssertEqual(messageLevel4.retainCount, (NSUInteger)1);
+ [messageLevel4 release];
+}
+
+- (void)testDefaultingArrays {
+ // Basic tests for default creation of arrays in a message.
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ TestRecursiveMessageWithRepeatedField *message2 =
+ [TestRecursiveMessageWithRepeatedField message];
+
+ // Simply accessing the array should not make any fields visible.
+ XCTAssertNotNil(message.a.a.iArray);
+ XCTAssertFalse([message hasA]);
+ XCTAssertFalse([message.a hasA]);
+ XCTAssertNotNil(message2.a.a.strArray);
+ XCTAssertFalse([message2 hasA]);
+ XCTAssertFalse([message2.a hasA]);
+
+ // But adding an element to the array should.
+ [message.a.a.iArray addValue:42];
+ XCTAssertTrue([message hasA]);
+ XCTAssertTrue([message.a hasA]);
+ XCTAssertEqual([message.a.a.iArray count], (NSUInteger)1);
+ [message2.a.a.strArray addObject:@"foo"];
+ XCTAssertTrue([message2 hasA]);
+ XCTAssertTrue([message2.a hasA]);
+ XCTAssertEqual([message2.a.a.strArray count], (NSUInteger)1);
+}
+
+- (void)testAutocreatedArrayShared {
+ // Multiple objects pointing to the same array.
+ TestRecursiveMessageWithRepeatedField *message1a =
+ [TestRecursiveMessageWithRepeatedField message];
+ TestRecursiveMessageWithRepeatedField *message1b =
+ [TestRecursiveMessageWithRepeatedField message];
+ message1a.a.iArray = message1b.a.iArray;
+ XCTAssertTrue([message1a hasA]);
+ XCTAssertFalse([message1b hasA]);
+ [message1a.a.iArray addValue:1];
+ XCTAssertTrue([message1a hasA]);
+ XCTAssertTrue([message1b hasA]);
+ XCTAssertEqual(message1a.a.iArray, message1b.a.iArray);
+
+ TestRecursiveMessageWithRepeatedField *message2a =
+ [TestRecursiveMessageWithRepeatedField message];
+ TestRecursiveMessageWithRepeatedField *message2b =
+ [TestRecursiveMessageWithRepeatedField message];
+ message2a.a.strArray = message2b.a.strArray;
+ XCTAssertTrue([message2a hasA]);
+ XCTAssertFalse([message2b hasA]);
+ [message2a.a.strArray addObject:@"bar"];
+ XCTAssertTrue([message2a hasA]);
+ XCTAssertTrue([message2b hasA]);
+ XCTAssertEqual(message2a.a.strArray, message2b.a.strArray);
+}
+
+- (void)testAutocreatedArrayCopy {
+ // Copy should not copy autocreated arrays.
+ TestAllTypes *message = [TestAllTypes message];
+ XCTAssertNotNil(message.repeatedStringArray);
+ XCTAssertNotNil(message.repeatedInt32Array);
+ TestAllTypes *message2 = [[message copy] autorelease];
+ // Pointer conparisions.
+ XCTAssertNotEqual(message.repeatedStringArray, message2.repeatedStringArray);
+ XCTAssertNotEqual(message.repeatedInt32Array, message2.repeatedInt32Array);
+
+ // Mutable copy should copy empty arrays that were explicitly set (end up
+ // with different objects that are equal).
+ TestAllTypes *message3 = [TestAllTypes message];
+ message3.repeatedInt32Array = [GPBInt32Array arrayWithValue:42];
+ message3.repeatedStringArray = [NSMutableArray arrayWithObject:@"wee"];
+ XCTAssertNotNil(message.repeatedInt32Array);
+ XCTAssertNotNil(message.repeatedStringArray);
+ TestAllTypes *message4 = [message3 copy];
+ XCTAssertNotEqual(message3.repeatedInt32Array, message4.repeatedInt32Array);
+ XCTAssertEqualObjects(message3.repeatedInt32Array,
+ message4.repeatedInt32Array);
+ XCTAssertNotEqual(message3.repeatedStringArray, message4.repeatedStringArray);
+ XCTAssertEqualObjects(message3.repeatedStringArray,
+ message4.repeatedStringArray);
+}
+
+- (void)testAutocreatedArrayRetain {
+ // Should be able to retain autocreated array while the creator is dealloced.
+ TestAllTypes *message = [TestAllTypes message];
+
+ @autoreleasepool {
+ TestAllTypes *message2 = [TestAllTypes message];
+ message.repeatedInt32Array = message2.repeatedInt32Array;
+ message.repeatedStringArray = message2.repeatedStringArray;
+ // Pointer conparision
+ XCTAssertEqual(message.repeatedInt32Array->_autocreator, message2);
+ XCTAssertTrue([message.repeatedStringArray
+ isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(
+ ((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator,
+ message2);
+ }
+
+ XCTAssertNil(message.repeatedInt32Array->_autocreator);
+ XCTAssertTrue(
+ [message.repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertNil(
+ ((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator);
+}
+
+- (void)testSetNilAutocreatedArray {
+ // Setting array to nil should cause it to lose its delegate.
+ TestAllTypes *message = [TestAllTypes message];
+ GPBInt32Array *repeatedInt32Array = [message.repeatedInt32Array retain];
+ GPBAutocreatedArray *repeatedStringArray =
+ (GPBAutocreatedArray *)[message.repeatedStringArray retain];
+ XCTAssertTrue([repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(repeatedInt32Array->_autocreator, message);
+ XCTAssertEqual(repeatedStringArray->_autocreator, message);
+ message.repeatedInt32Array = nil;
+ message.repeatedStringArray = nil;
+ XCTAssertNil(repeatedInt32Array->_autocreator);
+ XCTAssertNil(repeatedStringArray->_autocreator);
+ [repeatedInt32Array release];
+ [repeatedStringArray release];
+}
+
+- (void)testReplaceAutocreatedArray {
+ // Replacing array should orphan the old one and cause its creator to become
+ // visible.
+ {
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ XCTAssertNotNil(message.a);
+ XCTAssertNotNil(message.a.iArray);
+ XCTAssertFalse([message hasA]);
+ GPBInt32Array *iArray = [message.a.iArray retain];
+ XCTAssertEqual(iArray->_autocreator, message.a); // Pointer comparision
+ message.a.iArray = [GPBInt32Array arrayWithValue:1];
+ XCTAssertTrue([message hasA]);
+ XCTAssertNotEqual(message.a.iArray, iArray); // Pointer comparision
+ XCTAssertNil(iArray->_autocreator);
+ [iArray release];
+ }
+
+ {
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ XCTAssertNotNil(message.a);
+ XCTAssertNotNil(message.a.strArray);
+ XCTAssertFalse([message hasA]);
+ GPBAutocreatedArray *strArray =
+ (GPBAutocreatedArray *)[message.a.strArray retain];
+ XCTAssertTrue([strArray isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertEqual(strArray->_autocreator, message.a); // Pointer comparision
+ message.a.strArray = [NSMutableArray arrayWithObject:@"foo"];
+ XCTAssertTrue([message hasA]);
+ XCTAssertNotEqual(message.a.strArray, strArray); // Pointer comparision
+ XCTAssertNil(strArray->_autocreator);
+ [strArray release];
+ }
+}
+
+- (void)testSetAutocreatedArrayToSelf {
+ // Setting array to itself should cause it to become visible.
+ {
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ XCTAssertNotNil(message.a);
+ XCTAssertNotNil(message.a.iArray);
+ XCTAssertFalse([message hasA]);
+ message.a.iArray = message.a.iArray;
+ XCTAssertTrue([message hasA]);
+ XCTAssertNil(message.a.iArray->_autocreator);
+ }
+
+ {
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ XCTAssertNotNil(message.a);
+ XCTAssertNotNil(message.a.strArray);
+ XCTAssertFalse([message hasA]);
+ message.a.strArray = message.a.strArray;
+ XCTAssertTrue([message hasA]);
+ XCTAssertTrue([message.a.strArray isKindOfClass:[GPBAutocreatedArray class]]);
+ XCTAssertNil(((GPBAutocreatedArray *)message.a.strArray)->_autocreator);
+ }
+}
+
+- (void)testAutocreatedArrayRemoveAllValues {
+ // Calling removeAllValues on autocreated array should not cause it to be
+ // visible.
+ TestRecursiveMessageWithRepeatedField *message =
+ [TestRecursiveMessageWithRepeatedField message];
+ [message.a.iArray removeAll];
+ XCTAssertFalse([message hasA]);
+ [message.a.strArray removeAllObjects];
+ XCTAssertFalse([message hasA]);
+}
+
+- (void)testExtensionAccessors {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+ [self assertAllExtensionsSet:message repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testExtensionRepeatedSetters {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+ [self modifyRepeatedExtensions:message];
+ [self assertRepeatedExtensionsModified:message
+ repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testExtensionDefaults {
+ [self assertExtensionsClear:[TestAllExtensions message]];
+}
+
+- (void)testExtensionIsEquals {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+ [self modifyRepeatedExtensions:message];
+ TestAllExtensions *message2 = [TestAllExtensions message];
+ [self setAllExtensions:message2 repeatedCount:kGPBDefaultRepeatCount];
+ XCTAssertFalse([message isEqual:message2]);
+ message2 = [TestAllExtensions message];
+ [self setAllExtensions:message2 repeatedCount:kGPBDefaultRepeatCount];
+ [self modifyRepeatedExtensions:message2];
+ XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testExtensionsMergeFrom {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+ [self modifyRepeatedExtensions:message];
+
+ message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
+ TestAllExtensions *message2 = [TestAllExtensions message];
+ [self modifyRepeatedExtensions:message2];
+ [message2 mergeFrom:message];
+
+ XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testDefaultingExtensionMessages {
+ TestAllExtensions *message = [TestAllExtensions message];
+
+ // Initially they should all not have values.
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+ XCTAssertFalse([message
+ hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+
+ // They should auto create something when fetched.
+
+ TestAllTypes_OptionalGroup *optionalGroup =
+ [message getExtension:[UnittestRoot optionalGroupExtension]];
+ TestAllTypes_NestedMessage *optionalNestedMessage =
+ [message getExtension:[UnittestRoot optionalNestedMessageExtension]];
+ ForeignMessage *optionalForeignMessage =
+ [message getExtension:[UnittestRoot optionalForeignMessageExtension]];
+ ImportMessage *optionalImportMessage =
+ [message getExtension:[UnittestRoot optionalImportMessageExtension]];
+ PublicImportMessage *optionalPublicImportMessage = [message
+ getExtension:[UnittestRoot optionalPublicImportMessageExtension]];
+ TestAllTypes_NestedMessage *optionalLazyMessage =
+ [message getExtension:[UnittestRoot optionalLazyMessageExtension]];
+
+ XCTAssertNotNil(optionalGroup);
+ XCTAssertNotNil(optionalNestedMessage);
+ XCTAssertNotNil(optionalForeignMessage);
+ XCTAssertNotNil(optionalImportMessage);
+ XCTAssertNotNil(optionalPublicImportMessage);
+ XCTAssertNotNil(optionalLazyMessage);
+
+ // Although it auto-created empty messages, it should not show that it has
+ // them.
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+
+ // And they set that value back in to the message since the value created was
+ // mutable (so a second fetch should give the same object).
+
+ XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]],
+ optionalGroup);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalNestedMessageExtension]],
+ optionalNestedMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalForeignMessageExtension]],
+ optionalForeignMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalImportMessageExtension]],
+ optionalImportMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+ optionalPublicImportMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalLazyMessageExtension]],
+ optionalLazyMessage);
+
+ // And the default objects for a second message should be distinct (again,
+ // since they are mutable, each needs their own copy).
+
+ TestAllExtensions *message2 = [TestAllExtensions message];
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalGroupExtension]],
+ optionalGroup);
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalNestedMessageExtension]],
+ optionalNestedMessage);
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalForeignMessageExtension]],
+ optionalForeignMessage);
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalImportMessageExtension]],
+ optionalImportMessage);
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+ optionalPublicImportMessage);
+ XCTAssertNotEqual(
+ [message2 getExtension:[UnittestRoot optionalLazyMessageExtension]],
+ optionalLazyMessage);
+
+ // Clear values, and on next access you get back new submessages.
+
+ [message setExtension:[UnittestRoot optionalGroupExtension] value:nil];
+ [message setExtension:[UnittestRoot optionalGroupExtension] value:nil];
+ [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+ value:nil];
+ [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+ value:nil];
+ [message setExtension:[UnittestRoot optionalImportMessageExtension]
+ value:nil];
+ [message setExtension:[UnittestRoot optionalPublicImportMessageExtension]
+ value:nil];
+ [message setExtension:[UnittestRoot optionalLazyMessageExtension] value:nil];
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+ XCTAssertFalse([message
+ hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+ XCTAssertFalse(
+ [message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+
+ XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]],
+ optionalGroup);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalNestedMessageExtension]],
+ optionalNestedMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalForeignMessageExtension]],
+ optionalForeignMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalImportMessageExtension]],
+ optionalImportMessage);
+ XCTAssertEqual(
+ [message
+ getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+ optionalPublicImportMessage);
+ XCTAssertEqual(
+ [message getExtension:[UnittestRoot optionalLazyMessageExtension]],
+ optionalLazyMessage);
+}
+
+- (void)testMultiplePointersToAutocreatedExtension {
+ // 2 objects point to the same auto-created extension. One should "has" it.
+ // The other should not.
+ TestAllExtensions *message = [TestAllExtensions message];
+ TestAllExtensions *message2 = [TestAllExtensions message];
+ GPBExtensionField *extension = [UnittestRoot optionalGroupExtension];
+ [message setExtension:extension value:[message2 getExtension:extension]];
+ XCTAssertEqual([message getExtension:extension],
+ [message2 getExtension:extension]);
+ XCTAssertFalse([message2 hasExtension:extension]);
+ XCTAssertTrue([message hasExtension:extension]);
+
+ TestAllTypes_OptionalGroup *extensionValue =
+ [message2 getExtension:extension];
+ extensionValue.a = 1;
+ XCTAssertTrue([message2 hasExtension:extension]);
+ XCTAssertTrue([message hasExtension:extension]);
+}
+
+- (void)testCopyWithAutocreatedExtension {
+ // Mutable copy shouldn't copy autocreated extensions.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *optionalGroupExtension =
+ [UnittestRoot optionalGroupExtension];
+ GPBExtensionField *optionalNestedMessageExtesion =
+ [UnittestRoot optionalNestedMessageExtension];
+ TestAllTypes_OptionalGroup *optionalGroup =
+ [message getExtension:optionalGroupExtension];
+ optionalGroup.a = 42;
+ XCTAssertNotNil(optionalGroup);
+ XCTAssertNotNil([message getExtension:optionalNestedMessageExtesion]);
+ XCTAssertTrue([message hasExtension:optionalGroupExtension]);
+ XCTAssertFalse([message hasExtension:optionalNestedMessageExtesion]);
+
+ TestAllExtensions *message2 = [[message copy] autorelease];
+
+ // message2 should end up with its own copy of the optional group.
+ XCTAssertTrue([message2 hasExtension:optionalGroupExtension]);
+ XCTAssertEqualObjects([message getExtension:optionalGroupExtension],
+ [message2 getExtension:optionalGroupExtension]);
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual([message getExtension:optionalGroupExtension],
+ [message2 getExtension:optionalGroupExtension]);
+
+ XCTAssertFalse([message2 hasExtension:optionalNestedMessageExtesion]);
+ // Intentionally doing a pointer comparison (auto creation should be
+ // different)
+ XCTAssertNotEqual([message getExtension:optionalNestedMessageExtesion],
+ [message2 getExtension:optionalNestedMessageExtesion]);
+}
+
+- (void)testClearMessageAutocreatedExtension {
+ // Call clear should cause it to recreate its autocreated extensions.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *optionalGroupExtension =
+ [UnittestRoot optionalGroupExtension];
+ TestAllTypes_OptionalGroup *optionalGroup =
+ [[message getExtension:optionalGroupExtension] retain];
+ [message clear];
+ TestAllTypes_OptionalGroup *optionalGroupNew =
+ [message getExtension:optionalGroupExtension];
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(optionalGroup, optionalGroupNew);
+ [optionalGroup release];
+}
+
+- (void)testRetainAutocreatedExtension {
+ // Should be able to retain autocreated extension while the creator is
+ // dealloced.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *optionalGroupExtension =
+ [UnittestRoot optionalGroupExtension];
+
+ @autoreleasepool {
+ TestAllExtensions *message2 = [TestAllExtensions message];
+ [message setExtension:optionalGroupExtension
+ value:[message2 getExtension:optionalGroupExtension]];
+ XCTAssertTrue(GPBWasMessageAutocreatedBy(
+ [message getExtension:optionalGroupExtension], message2));
+ }
+
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(
+ [message getExtension:optionalGroupExtension], message));
+}
+
+- (void)testClearAutocreatedExtension {
+ // Clearing autocreated extension should NOT cause it to lose its creator.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *optionalGroupExtension =
+ [UnittestRoot optionalGroupExtension];
+ TestAllTypes_OptionalGroup *optionalGroup =
+ [[message getExtension:optionalGroupExtension] retain];
+ [message clearExtension:optionalGroupExtension];
+ TestAllTypes_OptionalGroup *optionalGroupNew =
+ [message getExtension:optionalGroupExtension];
+ XCTAssertEqual(optionalGroup, optionalGroupNew);
+ XCTAssertFalse([message hasExtension:optionalGroupExtension]);
+ [optionalGroup release];
+
+ // Clearing autocreated extension should not cause its creator to become
+ // visible
+ GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+ TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension];
+ TestAllExtensions *message_lvl3 =
+ [message_lvl2 getExtension:recursiveExtension];
+ [message_lvl3 clearExtension:recursiveExtension];
+ XCTAssertFalse([message hasExtension:recursiveExtension]);
+}
+
+- (void)testSetAutocreatedExtensionBecomesVisible {
+ // Setting an extension should cause the extension to appear to its creator.
+ // Test this several levels deep.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+ TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension];
+ TestAllExtensions *message_lvl3 =
+ [message_lvl2 getExtension:recursiveExtension];
+ TestAllExtensions *message_lvl4 =
+ [message_lvl3 getExtension:recursiveExtension];
+ XCTAssertFalse([message hasExtension:recursiveExtension]);
+ XCTAssertFalse([message_lvl2 hasExtension:recursiveExtension]);
+ XCTAssertFalse([message_lvl3 hasExtension:recursiveExtension]);
+ XCTAssertFalse([message_lvl4 hasExtension:recursiveExtension]);
+ [message_lvl4 setExtension:[UnittestRoot optionalInt32Extension] value:@(1)];
+ XCTAssertTrue([message hasExtension:recursiveExtension]);
+ XCTAssertTrue([message_lvl2 hasExtension:recursiveExtension]);
+ XCTAssertTrue([message_lvl3 hasExtension:recursiveExtension]);
+ XCTAssertFalse([message_lvl4 hasExtension:recursiveExtension]);
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl4, message_lvl3));
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl3, message_lvl2));
+ XCTAssertFalse(GPBWasMessageAutocreatedBy(message_lvl2, message));
+}
+
+- (void)testSetAutocreatedExtensionToSelf {
+ // Setting extension to itself should cause it to become visible.
+ TestAllExtensions *message = [TestAllExtensions message];
+ GPBExtensionField *optionalGroupExtension =
+ [UnittestRoot optionalGroupExtension];
+ XCTAssertNotNil([message getExtension:optionalGroupExtension]);
+ XCTAssertFalse([message hasExtension:optionalGroupExtension]);
+ [message setExtension:optionalGroupExtension
+ value:[message getExtension:optionalGroupExtension]];
+ XCTAssertTrue([message hasExtension:optionalGroupExtension]);
+}
+
+- (void)testAutocreatedExtensionMemoryLeaks {
+ GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+
+ // Test for memory leaks with autocreated extensions.
+ TestAllExtensions *message;
+ TestAllExtensions *message_lvl2;
+ TestAllExtensions *message_lvl3;
+ TestAllExtensions *message_lvl4;
+ @autoreleasepool {
+ message = [[TestAllExtensions alloc] init];
+ message_lvl2 = [[message getExtension:recursiveExtension] retain];
+ message_lvl3 = [[message_lvl2 getExtension:recursiveExtension] retain];
+ message_lvl4 = [[message_lvl3 getExtension:recursiveExtension] retain];
+ [message_lvl2 setExtension:[UnittestRoot optionalInt32Extension]
+ value:@(1)];
+ }
+
+ XCTAssertEqual(message.retainCount, (NSUInteger)1);
+ @autoreleasepool {
+ [message release];
+ }
+ XCTAssertEqual(message_lvl2.retainCount, (NSUInteger)1);
+ @autoreleasepool {
+ [message_lvl2 release];
+ }
+ XCTAssertEqual(message_lvl3.retainCount, (NSUInteger)1);
+ @autoreleasepool {
+ [message_lvl3 release];
+ }
+ XCTAssertEqual(message_lvl4.retainCount, (NSUInteger)1);
+ [message_lvl4 release];
+}
+
+- (void)testSetExtensionWithAutocreatedValue {
+ GPBExtensionField *recursiveExtension = [UnittestObjcRoot recursiveExtension];
+
+ TestAllExtensions *message;
+ @autoreleasepool {
+ message = [[TestAllExtensions alloc] init];
+ [message getExtension:recursiveExtension];
+ }
+
+ // This statements checks that the extension value isn't accidentally
+ // dealloced when removing it from the autocreated map.
+ [message setExtension:recursiveExtension
+ value:[message getExtension:recursiveExtension]];
+ XCTAssertTrue([message hasExtension:recursiveExtension]);
+ [message release];
+}
+
+- (void)testRecursion {
+ TestRecursiveMessage *message = [TestRecursiveMessage message];
+ XCTAssertNotNil(message.a);
+ XCTAssertNotNil(message.a.a);
+ XCTAssertEqual(message.a.a.i, 0);
+}
+
+- (void)testGenerateAndParseUnknownMessage {
+ GPBUnknownFieldSet *unknowns =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ [unknowns mergeVarintField:123 value:456];
+ GPBMessage *message = [GPBMessage message];
+ [message setUnknownFields:unknowns];
+ NSData *data = [message data];
+ GPBMessage *message2 = [GPBMessage parseFromData:data extensionRegistry:nil];
+ XCTAssertEqualObjects(message, message2);
+}
+
+- (void)testDelimitedWriteAndParseMultipleMessages {
+ GPBUnknownFieldSet *unknowns1 =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ [unknowns1 mergeVarintField:123 value:456];
+ GPBMessage *message1 = [GPBMessage message];
+ [message1 setUnknownFields:unknowns1];
+
+ GPBUnknownFieldSet *unknowns2 =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ [unknowns2 mergeVarintField:789 value:987];
+ [unknowns2 mergeVarintField:654 value:321];
+ GPBMessage *message2 = [GPBMessage message];
+ [message2 setUnknownFields:unknowns2];
+
+ NSMutableData *delimitedData = [NSMutableData data];
+ [delimitedData appendData:[message1 delimitedData]];
+ [delimitedData appendData:[message2 delimitedData]];
+ GPBCodedInputStream *input =
+ [GPBCodedInputStream streamWithData:delimitedData];
+ GPBMessage *message3 = [GPBMessage parseDelimitedFromCodedInputStream:input
+ extensionRegistry:nil];
+ GPBMessage *message4 = [GPBMessage parseDelimitedFromCodedInputStream:input
+ extensionRegistry:nil];
+ XCTAssertEqualObjects(message1, message3);
+ XCTAssertEqualObjects(message2, message4);
+}
+
+- (void)testDuplicateEnums {
+ XCTAssertEqual(TestEnumWithDupValue_Foo1, TestEnumWithDupValue_Foo2);
+}
+
+- (void)testWeirdDefaults {
+ ObjcWeirdDefaults *message = [ObjcWeirdDefaults message];
+ GPBDescriptor *descriptor = [[message class] descriptor];
+ GPBFieldDescriptor *fieldDesc = [descriptor fieldWithName:@"foo"];
+ XCTAssertNotNil(fieldDesc);
+ XCTAssertTrue(fieldDesc.hasDefaultValue);
+ XCTAssertFalse(message.hasFoo);
+ XCTAssertEqualObjects(message.foo, @"");
+
+ fieldDesc = [descriptor fieldWithName:@"bar"];
+ XCTAssertNotNil(fieldDesc);
+ XCTAssertTrue(fieldDesc.hasDefaultValue);
+ XCTAssertFalse(message.hasBar);
+ XCTAssertEqualObjects(message.bar, GPBEmptyNSData());
+}
+
+- (void)testEnumDescriptorFromExtensionDescriptor {
+ GPBExtensionField *extField = [UnittestRoot optionalForeignEnumExtension];
+ GPBExtensionDescriptor *extDescriptor = extField.descriptor;
+ XCTAssertEqual(extDescriptor.type, GPBTypeEnum);
+ GPBEnumDescriptor *enumDescriptor = extDescriptor.enumDescriptor;
+ GPBEnumDescriptor *expectedDescriptor = ForeignEnum_EnumDescriptor();
+ XCTAssertEqualObjects(enumDescriptor, expectedDescriptor);
+}
+
+- (void)testEnumNaming {
+ // objectivec_helpers.cc has some interesting cases to deal with in
+ // EnumValueName/EnumValueShortName. Confirm that things generated as
+ // expected.
+
+ // This block just has to compile to confirm we got the expected types/names.
+ // The *_IsValidValue() calls are just there to keep the projects warnings
+ // flags happy by providing use of the variables/values.
+
+ Foo aFoo = Foo_SerializedSize;
+ Foo_IsValidValue(aFoo);
+ aFoo = Foo_Size;
+ Foo_IsValidValue(aFoo);
+
+ Category_Enum aCat = Category_Enum_Red;
+ Category_Enum_IsValidValue(aCat);
+
+ Time aTime = Time_Base;
+ Time_IsValidValue(aTime);
+ aTime = Time_SomethingElse;
+ Time_IsValidValue(aTime);
+
+ // This block confirms the names in the decriptors is what we wanted.
+
+ GPBEnumDescriptor *descriptor;
+ NSString *valueName;
+
+ descriptor = Foo_EnumDescriptor();
+ XCTAssertNotNil(descriptor);
+ XCTAssertEqualObjects(@"Foo", descriptor.name);
+ valueName = [descriptor enumNameForValue:Foo_SerializedSize];
+ XCTAssertEqualObjects(@"Foo_SerializedSize", valueName);
+ valueName = [descriptor enumNameForValue:Foo_Size];
+ XCTAssertEqualObjects(@"Foo_Size", valueName);
+
+ descriptor = Category_Enum_EnumDescriptor();
+ XCTAssertNotNil(descriptor);
+ XCTAssertEqualObjects(@"Category_Enum", descriptor.name);
+ valueName = [descriptor enumNameForValue:Category_Enum_Red];
+ XCTAssertEqualObjects(@"Category_Enum_Red", valueName);
+
+ descriptor = Time_EnumDescriptor();
+ XCTAssertNotNil(descriptor);
+ XCTAssertEqualObjects(@"Time", descriptor.name);
+ valueName = [descriptor enumNameForValue:Time_Base];
+ XCTAssertEqualObjects(@"Time_Base", valueName);
+ valueName = [descriptor enumNameForValue:Time_SomethingElse];
+ XCTAssertEqualObjects(@"Time_SomethingElse", valueName);
+}
+
+- (void)testNegativeEnums {
+ EnumTestMsg *msg = [EnumTestMsg message];
+
+ // Defaults
+ XCTAssertEqual(msg.foo, EnumTestMsg_MyEnum_Zero);
+ XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_One);
+ XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegOne);
+ // Bounce to wire and back.
+ EnumTestMsg *msgPrime = [EnumTestMsg parseFromData:[msg data]];
+ XCTAssertEqualObjects(msgPrime, msg);
+ XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero);
+ XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_One);
+ XCTAssertEqual(msgPrime.baz, EnumTestMsg_MyEnum_NegOne);
+
+ // Other values
+ msg.bar = EnumTestMsg_MyEnum_Two;
+ msg.baz = EnumTestMsg_MyEnum_NegTwo;
+ XCTAssertEqual(msg.bar, EnumTestMsg_MyEnum_Two);
+ XCTAssertEqual(msg.baz, EnumTestMsg_MyEnum_NegTwo);
+ // Bounce to wire and back.
+ msgPrime = [EnumTestMsg parseFromData:[msg data]];
+ XCTAssertEqualObjects(msgPrime, msg);
+ XCTAssertEqual(msgPrime.foo, EnumTestMsg_MyEnum_Zero);
+ XCTAssertEqual(msgPrime.bar, EnumTestMsg_MyEnum_Two);
+ XCTAssertEqual(msgPrime.baz, EnumTestMsg_MyEnum_NegTwo);
+
+ // Repeated field (shouldn't ever be an issue since developer has to use the
+ // right GPBArray methods themselves).
+ msg.mumbleArray = [GPBEnumArray
+ arrayWithValidationFunction:EnumTestMsg_MyEnum_IsValidValue];
+ [msg.mumbleArray addValue:EnumTestMsg_MyEnum_Zero];
+ [msg.mumbleArray addValue:EnumTestMsg_MyEnum_One];
+ [msg.mumbleArray addValue:EnumTestMsg_MyEnum_Two];
+ [msg.mumbleArray addValue:EnumTestMsg_MyEnum_NegOne];
+ [msg.mumbleArray addValue:EnumTestMsg_MyEnum_NegTwo];
+ XCTAssertEqual([msg.mumbleArray valueAtIndex:0], EnumTestMsg_MyEnum_Zero);
+ XCTAssertEqual([msg.mumbleArray valueAtIndex:1], EnumTestMsg_MyEnum_One);
+ XCTAssertEqual([msg.mumbleArray valueAtIndex:2], EnumTestMsg_MyEnum_Two);
+ XCTAssertEqual([msg.mumbleArray valueAtIndex:3], EnumTestMsg_MyEnum_NegOne);
+ XCTAssertEqual([msg.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo);
+ // Bounce to wire and back.
+ msgPrime = [EnumTestMsg parseFromData:[msg data]];
+ XCTAssertEqualObjects(msgPrime, msg);
+ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:0],
+ EnumTestMsg_MyEnum_Zero);
+ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:1], EnumTestMsg_MyEnum_One);
+ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:2], EnumTestMsg_MyEnum_Two);
+ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:3],
+ EnumTestMsg_MyEnum_NegOne);
+ XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4],
+ EnumTestMsg_MyEnum_NegTwo);
+}
+
+- (void)testMutableNameManagling {
+ // These basically confirm that all the expected name mangling happened by not
+ // having compile errors.
+
+ // TODO(thomasvl): Write these, see unittest_name_mangling.proto.
+}
+
+@end
diff --git a/objectivec/Tests/GPBPerfTests.m b/objectivec/Tests/GPBPerfTests.m
new file mode 100644
index 00000000..d09021af
--- /dev/null
+++ b/objectivec/Tests/GPBPerfTests.m
@@ -0,0 +1,306 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 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 "GPBTestUtilities.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+
+//
+// This file really just uses the unittests framework as a testbed to
+// run some simple performance tests. The data can then be used to help
+// evaluate changes to the runtime.
+//
+
+static const uint32_t kRepeatedCount = 100;
+
+@interface PerfTests : GPBTestCase
+@end
+
+@implementation PerfTests
+
+- (void)setUp {
+ // A convenient place to put a break point if you want to connect instruments.
+ [super setUp];
+}
+
+- (void)testMessagePerformance {
+ [self measureBlock:^{
+ for (int i = 0; i < 200; ++i) {
+ TestAllTypes* message = [[TestAllTypes alloc] init];
+ [self setAllFields:message repeatedCount:kRepeatedCount];
+ NSData* rawBytes = [message data];
+ [message release];
+ message = [[TestAllTypes alloc] initWithData:rawBytes];
+ [message release];
+ }
+ }];
+}
+
+- (void)testExtensionsPerformance {
+ [self measureBlock:^{
+ for (int i = 0; i < 200; ++i) {
+ TestAllExtensions* message = [[TestAllExtensions alloc] init];
+ [self setAllExtensions:message repeatedCount:kRepeatedCount];
+ NSData* rawBytes = [message data];
+ [message release];
+ TestAllExtensions* message2 =
+ [[TestAllExtensions alloc] initWithData:rawBytes];
+ [message2 release];
+ }
+ }];
+}
+
+- (void)testPackedTypesPerformance {
+ [self measureBlock:^{
+ for (int i = 0; i < 1000; ++i) {
+ TestPackedTypes* message = [[TestPackedTypes alloc] init];
+ [self setPackedFields:message repeatedCount:kRepeatedCount];
+ NSData* rawBytes = [message data];
+ [message release];
+ message = [[TestPackedTypes alloc] initWithData:rawBytes];
+ [message release];
+ }
+ }];
+}
+
+- (void)testPackedExtensionsPerformance {
+ [self measureBlock:^{
+ for (int i = 0; i < 1000; ++i) {
+ TestPackedExtensions* message = [[TestPackedExtensions alloc] init];
+ [self setPackedExtensions:message repeatedCount:kRepeatedCount];
+ NSData* rawBytes = [message data];
+ [message release];
+ TestPackedExtensions* message2 =
+ [[TestPackedExtensions alloc] initWithData:rawBytes];
+ [message2 release];
+ }
+ }];
+}
+
+- (void)testHas {
+ TestAllTypes* message = [self allSetRepeatedCount:1];
+ [self measureBlock:^{
+ for (int i = 0; i < 10000; ++i) {
+ [message hasOptionalInt32];
+ message.hasOptionalInt32 = NO;
+ [message hasOptionalInt32];
+
+ [message hasOptionalInt64];
+ message.hasOptionalInt64 = NO;
+ [message hasOptionalInt64];
+
+ [message hasOptionalUint32];
+ message.hasOptionalUint32 = NO;
+ [message hasOptionalUint32];
+
+ [message hasOptionalUint64];
+ message.hasOptionalUint64 = NO;
+ [message hasOptionalUint64];
+
+ [message hasOptionalSint32];
+ message.hasOptionalSint32 = NO;
+ [message hasOptionalSint32];
+
+ [message hasOptionalSint64];
+ message.hasOptionalSint64 = NO;
+ [message hasOptionalSint64];
+
+ [message hasOptionalFixed32];
+ message.hasOptionalFixed32 = NO;
+ [message hasOptionalFixed32];
+
+ [message hasOptionalFixed64];
+ message.hasOptionalFixed64 = NO;
+ [message hasOptionalFixed64];
+
+ [message hasOptionalSfixed32];
+ message.hasOptionalSfixed32 = NO;
+ [message hasOptionalSfixed32];
+
+ [message hasOptionalSfixed64];
+ message.hasOptionalSfixed64 = NO;
+ [message hasOptionalSfixed64];
+
+ [message hasOptionalFloat];
+ message.hasOptionalFloat = NO;
+ [message hasOptionalFloat];
+
+ [message hasOptionalDouble];
+ message.hasOptionalDouble = NO;
+ [message hasOptionalDouble];
+
+ [message hasOptionalBool];
+ message.hasOptionalBool = NO;
+ [message hasOptionalBool];
+
+ [message hasOptionalString];
+ message.hasOptionalString = NO;
+ [message hasOptionalString];
+
+ [message hasOptionalBytes];
+ message.hasOptionalBytes = NO;
+ [message hasOptionalBytes];
+
+ [message hasOptionalGroup];
+ message.hasOptionalGroup = NO;
+ [message hasOptionalGroup];
+
+ [message hasOptionalNestedMessage];
+ message.hasOptionalNestedMessage = NO;
+ [message hasOptionalNestedMessage];
+
+ [message hasOptionalForeignMessage];
+ message.hasOptionalForeignMessage = NO;
+ [message hasOptionalForeignMessage];
+
+ [message hasOptionalImportMessage];
+ message.hasOptionalImportMessage = NO;
+ [message hasOptionalImportMessage];
+
+ [message.optionalGroup hasA];
+ message.optionalGroup.hasA = NO;
+ [message.optionalGroup hasA];
+
+ [message.optionalNestedMessage hasBb];
+ message.optionalNestedMessage.hasBb = NO;
+ [message.optionalNestedMessage hasBb];
+
+ [message.optionalForeignMessage hasC];
+ message.optionalForeignMessage.hasC = NO;
+ [message.optionalForeignMessage hasC];
+
+ [message.optionalImportMessage hasD];
+ message.optionalImportMessage.hasD = NO;
+ [message.optionalImportMessage hasD];
+
+ [message hasOptionalNestedEnum];
+ message.hasOptionalNestedEnum = NO;
+ [message hasOptionalNestedEnum];
+
+ [message hasOptionalForeignEnum];
+ message.hasOptionalForeignEnum = NO;
+ [message hasOptionalForeignEnum];
+
+ [message hasOptionalImportEnum];
+ message.hasOptionalImportEnum = NO;
+ [message hasOptionalImportEnum];
+
+ [message hasOptionalStringPiece];
+ message.hasOptionalStringPiece = NO;
+ [message hasOptionalStringPiece];
+
+ [message hasOptionalCord];
+ message.hasOptionalCord = NO;
+ [message hasOptionalCord];
+
+ [message hasDefaultInt32];
+ message.hasDefaultInt32 = NO;
+ [message hasDefaultInt32];
+
+ [message hasDefaultInt64];
+ message.hasDefaultInt64 = NO;
+ [message hasDefaultInt64];
+
+ [message hasDefaultUint32];
+ message.hasDefaultUint32 = NO;
+ [message hasDefaultUint32];
+
+ [message hasDefaultUint64];
+ message.hasDefaultUint64 = NO;
+ [message hasDefaultUint64];
+
+ [message hasDefaultSint32];
+ message.hasDefaultSint32 = NO;
+ [message hasDefaultSint32];
+
+ [message hasDefaultSint64];
+ message.hasDefaultSint64 = NO;
+ [message hasDefaultSint64];
+
+ [message hasDefaultFixed32];
+ message.hasDefaultFixed32 = NO;
+ [message hasDefaultFixed32];
+
+ [message hasDefaultFixed64];
+ message.hasDefaultFixed64 = NO;
+ [message hasDefaultFixed64];
+
+ [message hasDefaultSfixed32];
+ message.hasDefaultSfixed32 = NO;
+ [message hasDefaultSfixed32];
+
+ [message hasDefaultSfixed64];
+ message.hasDefaultSfixed64 = NO;
+ [message hasDefaultSfixed64];
+
+ [message hasDefaultFloat];
+ message.hasDefaultFloat = NO;
+ [message hasDefaultFloat];
+
+ [message hasDefaultDouble];
+ message.hasDefaultDouble = NO;
+ [message hasDefaultDouble];
+
+ [message hasDefaultBool];
+ message.hasDefaultBool = NO;
+ [message hasDefaultBool];
+
+ [message hasDefaultString];
+ message.hasDefaultString = NO;
+ [message hasDefaultString];
+
+ [message hasDefaultBytes];
+ message.hasDefaultBytes = NO;
+ [message hasDefaultBytes];
+
+ [message hasDefaultNestedEnum];
+ message.hasDefaultNestedEnum = NO;
+ [message hasDefaultNestedEnum];
+
+ [message hasDefaultForeignEnum];
+ message.hasDefaultForeignEnum = NO;
+ [message hasDefaultForeignEnum];
+
+ [message hasDefaultImportEnum];
+ message.hasDefaultImportEnum = NO;
+ [message hasDefaultImportEnum];
+
+ [message hasDefaultStringPiece];
+ message.hasDefaultStringPiece = NO;
+ [message hasDefaultStringPiece];
+
+ [message hasDefaultCord];
+ message.hasDefaultCord = NO;
+ [message hasDefaultCord];
+ }
+ }];
+}
+
+@end
diff --git a/objectivec/Tests/GPBStringTests.m b/objectivec/Tests/GPBStringTests.m
new file mode 100644
index 00000000..30f13775
--- /dev/null
+++ b/objectivec/Tests/GPBStringTests.m
@@ -0,0 +1,516 @@
+// 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"
+
+#ifndef GPBARRAYSIZE
+#define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
+#endif // GPBARRAYSIZE
+
+@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
diff --git a/objectivec/Tests/GPBSwiftTests.swift b/objectivec/Tests/GPBSwiftTests.swift
new file mode 100644
index 00000000..e7b6f94c
--- /dev/null
+++ b/objectivec/Tests/GPBSwiftTests.swift
@@ -0,0 +1,405 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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
+import XCTest
+
+// Test some usage of the ObjC library from Swift.
+
+class GPBBridgeTests: XCTestCase {
+
+ func testProto2Basics() {
+ let msg = Message2()
+ let msg2 = Message2()
+ let msg3 = Message2_OptionalGroup()
+
+ msg.optionalInt32 = 100
+ msg.optionalString = "abc"
+ msg.optionalEnum = .Bar
+ msg2.optionalString = "other"
+ msg.optionalMessage = msg2
+ msg3.a = 200
+ msg.optionalGroup = msg3
+ msg.repeatedInt32Array.addValue(300)
+ msg.repeatedInt32Array.addValue(301)
+ msg.repeatedStringArray.addObject("mno")
+ msg.repeatedStringArray.addObject("pqr")
+ msg.repeatedEnumArray.addValue(Message2_Enum.Bar.rawValue)
+ msg.repeatedEnumArray.addValue(Message2_Enum.Baz.rawValue)
+
+ // Check has*.
+ XCTAssertTrue(msg.hasOptionalInt32)
+ XCTAssertTrue(msg.hasOptionalString)
+ XCTAssertTrue(msg.hasOptionalEnum)
+ XCTAssertTrue(msg2.hasOptionalString)
+ XCTAssertTrue(msg.hasOptionalMessage)
+ XCTAssertTrue(msg3.hasA)
+ XCTAssertTrue(msg.hasOptionalGroup)
+ XCTAssertFalse(msg.hasOptionalInt64)
+ XCTAssertFalse(msg.hasOptionalFloat)
+
+ // Check values.
+ XCTAssertEqual(msg.optionalInt32, Int32(100))
+ XCTAssertEqual(msg.optionalString, "abc")
+ XCTAssertEqual(msg2.optionalString, "other")
+ XCTAssertTrue(msg.optionalMessage === msg2)
+ XCTAssertEqual(msg.optionalEnum, Message2_Enum.Bar)
+ XCTAssertEqual(msg3.a, Int32(200))
+ XCTAssertTrue(msg.optionalGroup === msg3)
+ XCTAssertEqual(msg.repeatedInt32Array.count, UInt(2))
+ XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(0), Int32(300))
+ XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(1), Int32(301))
+ XCTAssertEqual(msg.repeatedStringArray.count, Int(2))
+ XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as! String, "mno")
+ XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as! String, "pqr")
+ XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2))
+ XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message2_Enum.Bar.rawValue)
+ XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(1), Message2_Enum.Baz.rawValue)
+ XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0))
+
+ // Clearing a string with nil.
+ msg2.optionalString = nil
+ XCTAssertFalse(msg2.hasOptionalString)
+ XCTAssertEqual(msg2.optionalString, "")
+
+ // Clearing a message with nil.
+ msg.optionalGroup = nil
+ XCTAssertFalse(msg.hasOptionalGroup)
+ XCTAssertTrue(msg.optionalGroup !== msg3) // New instance
+
+ // Clear.
+ msg.clear()
+ XCTAssertFalse(msg.hasOptionalInt32)
+ XCTAssertFalse(msg.hasOptionalString)
+ XCTAssertFalse(msg.hasOptionalEnum)
+ XCTAssertFalse(msg.hasOptionalMessage)
+ XCTAssertFalse(msg.hasOptionalInt64)
+ XCTAssertFalse(msg.hasOptionalFloat)
+ XCTAssertEqual(msg.optionalInt32, Int32(0))
+ XCTAssertEqual(msg.optionalString, "")
+ XCTAssertTrue(msg.optionalMessage !== msg2) // New instance
+ XCTAssertEqual(msg.optionalEnum, Message2_Enum.Foo) // Default
+ XCTAssertEqual(msg.repeatedInt32Array.count, UInt(0))
+ XCTAssertEqual(msg.repeatedStringArray.count, Int(0))
+ XCTAssertEqual(msg.repeatedEnumArray.count, UInt(0))
+ }
+
+ func testProto3Basics() {
+ let msg = Message3()
+ let msg2 = Message3()
+
+ msg.optionalInt32 = 100
+ msg.optionalString = "abc"
+ msg.optionalEnum = .Bar
+ msg2.optionalString = "other"
+ msg.optionalMessage = msg2
+ msg.repeatedInt32Array.addValue(300)
+ msg.repeatedInt32Array.addValue(301)
+ msg.repeatedStringArray.addObject("mno")
+ msg.repeatedStringArray.addObject("pqr")
+ // "proto3" syntax lets enum get unknown values.
+ msg.repeatedEnumArray.addValue(Message3_Enum.Bar.rawValue)
+ msg.repeatedEnumArray.addRawValue(666)
+ SetMessage3_OptionalEnum_RawValue(msg2, 666)
+
+ // Has only exists on for message fields.
+ XCTAssertTrue(msg.hasOptionalMessage)
+ XCTAssertFalse(msg2.hasOptionalMessage)
+
+ // Check values.
+ XCTAssertEqual(msg.optionalInt32, Int32(100))
+ XCTAssertEqual(msg.optionalString, "abc")
+ XCTAssertEqual(msg2.optionalString, "other")
+ XCTAssertTrue(msg.optionalMessage === msg2)
+ XCTAssertEqual(msg.optionalEnum, Message3_Enum.Bar)
+ XCTAssertEqual(msg.repeatedInt32Array.count, UInt(2))
+ XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(0), Int32(300))
+ XCTAssertEqual(msg.repeatedInt32Array.valueAtIndex(1), Int32(301))
+ XCTAssertEqual(msg.repeatedStringArray.count, Int(2))
+ XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(0) as! String, "mno")
+ XCTAssertEqual(msg.repeatedStringArray.objectAtIndex(1) as! String, "pqr")
+ XCTAssertEqual(msg.repeatedInt64Array.count, UInt(0))
+ XCTAssertEqual(msg.repeatedEnumArray.count, UInt(2))
+ XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(0), Message3_Enum.Bar.rawValue)
+ XCTAssertEqual(msg.repeatedEnumArray.valueAtIndex(1), Message3_Enum.GPBUnrecognizedEnumeratorValue.rawValue)
+ XCTAssertEqual(msg.repeatedEnumArray.rawValueAtIndex(1), 666)
+ XCTAssertEqual(msg2.optionalEnum, Message3_Enum.GPBUnrecognizedEnumeratorValue)
+ XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Int32(666))
+
+ // Clearing a string with nil.
+ msg2.optionalString = nil
+ XCTAssertEqual(msg2.optionalString, "")
+
+ // Clearing a message with nil.
+ msg.optionalMessage = nil
+ XCTAssertFalse(msg.hasOptionalMessage)
+ XCTAssertTrue(msg.optionalMessage !== msg2) // New instance
+
+ // Clear.
+ msg.clear()
+ XCTAssertFalse(msg.hasOptionalMessage)
+ XCTAssertEqual(msg.optionalInt32, Int32(0))
+ XCTAssertEqual(msg.optionalString, "")
+ XCTAssertTrue(msg.optionalMessage !== msg2) // New instance
+ XCTAssertEqual(msg.optionalEnum, Message3_Enum.Foo) // Default
+ XCTAssertEqual(msg.repeatedInt32Array.count, UInt(0))
+ XCTAssertEqual(msg.repeatedStringArray.count, Int(0))
+ XCTAssertEqual(msg.repeatedEnumArray.count, UInt(0))
+ msg2.clear()
+ XCTAssertEqual(msg2.optionalEnum, Message3_Enum.Foo) // Default
+ XCTAssertEqual(Message3_OptionalEnum_RawValue(msg2), Message3_Enum.Foo.rawValue)
+ }
+
+ func testAutoCreation() {
+ let msg = Message2()
+
+ XCTAssertFalse(msg.hasOptionalGroup)
+ XCTAssertFalse(msg.hasOptionalMessage)
+
+ // Access shouldn't result in has* but should return objects.
+ let msg2 = msg.optionalGroup
+ let msg3 = msg.optionalMessage.optionalMessage
+ let msg4 = msg.optionalMessage
+ XCTAssertNotNil(msg2)
+ XCTAssertNotNil(msg3)
+ XCTAssertFalse(msg.hasOptionalGroup)
+ XCTAssertFalse(msg.optionalMessage.hasOptionalMessage)
+ XCTAssertFalse(msg.hasOptionalMessage)
+
+ // Setting things should trigger has* getting set.
+ msg.optionalGroup.a = 10
+ msg.optionalMessage.optionalMessage.optionalInt32 = 100
+ XCTAssertTrue(msg.hasOptionalGroup)
+ XCTAssertTrue(msg.optionalMessage.hasOptionalMessage)
+ XCTAssertTrue(msg.hasOptionalMessage)
+
+ // And they should be the same pointer as before.
+ XCTAssertTrue(msg2 === msg.optionalGroup)
+ XCTAssertTrue(msg3 === msg.optionalMessage.optionalMessage)
+ XCTAssertTrue(msg4 === msg.optionalMessage)
+
+ // Clear gets us new objects next time around.
+ msg.clear()
+ XCTAssertFalse(msg.hasOptionalGroup)
+ XCTAssertFalse(msg.optionalMessage.hasOptionalMessage)
+ XCTAssertFalse(msg.hasOptionalMessage)
+ msg.optionalGroup.a = 20
+ msg.optionalMessage.optionalMessage.optionalInt32 = 200
+ XCTAssertTrue(msg.hasOptionalGroup)
+ XCTAssertTrue(msg.optionalMessage.hasOptionalMessage)
+ XCTAssertTrue(msg.hasOptionalMessage)
+ XCTAssertTrue(msg2 !== msg.optionalGroup)
+ XCTAssertTrue(msg3 !== msg.optionalMessage.optionalMessage)
+ XCTAssertTrue(msg4 !== msg.optionalMessage)
+
+ // Explicit set of a message, means autocreated object doesn't bind.
+ msg.clear()
+ let autoCreated = msg.optionalMessage
+ XCTAssertFalse(msg.hasOptionalMessage)
+ let msg5 = Message2()
+ msg5.optionalInt32 = 123
+ msg.optionalMessage = msg5
+ XCTAssertTrue(msg.hasOptionalMessage)
+ // Modifing the autocreated doesn't replaced the explicit set one.
+ autoCreated.optionalInt32 = 456
+ XCTAssertTrue(msg.hasOptionalMessage)
+ XCTAssertTrue(msg.optionalMessage === msg5)
+ XCTAssertEqual(msg.optionalMessage.optionalInt32, Int32(123))
+ }
+
+ func testProto2OneOfSupport() {
+ let msg = Message2()
+
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default
+ let autoCreated = msg.oneofMessage // Default create one.
+ XCTAssertNotNil(autoCreated)
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+
+ msg.oneofInt32 = 10
+ XCTAssertEqual(msg.oneofInt32, Int32(10))
+ XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofInt32)
+
+ msg.oneofFloat = 20.0
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(20.0))
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofFloat)
+
+ msg.oneofEnum = .Bar
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Bar)
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofEnum)
+
+ // Sets via the autocreated instance.
+ msg.oneofMessage.optionalInt32 = 200
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(200))
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofMessage)
+
+ // Clear the oneof.
+ Message2_ClearOOneOfCase(msg)
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(110.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message2_Enum.Baz) // Default
+ let autoCreated2 = msg.oneofMessage // Default create one
+ XCTAssertNotNil(autoCreated2)
+ XCTAssertTrue(autoCreated2 !== autoCreated) // New instance
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+
+ msg.oneofInt32 = 10
+ XCTAssertEqual(msg.oneofInt32, Int32(10))
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofInt32)
+
+ // Confirm Message.clear() handles the oneof correctly.
+ msg.clear()
+ XCTAssertEqual(msg.oneofInt32, Int32(100)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+
+ // Sets via the autocreated instance.
+ msg.oneofMessage.optionalInt32 = 300
+ XCTAssertTrue(msg.oneofMessage !== autoCreated) // New instance
+ XCTAssertTrue(msg.oneofMessage !== autoCreated2) // New instance
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(300))
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.OneofMessage)
+
+ // Set message to nil clears the oneof.
+ msg.oneofMessage = nil
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase.GPBUnsetOneOfCase)
+}
+
+ func testProto3OneOfSupport() {
+ let msg = Message3()
+
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default
+ let autoCreated = msg.oneofMessage // Default create one.
+ XCTAssertNotNil(autoCreated)
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+
+ msg.oneofInt32 = 10
+ XCTAssertEqual(msg.oneofInt32, Int32(10))
+ XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofInt32)
+
+ msg.oneofFloat = 20.0
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(20.0))
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofFloat)
+
+ msg.oneofEnum = .Bar
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Bar)
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofEnum)
+
+ // Sets via the autocreated instance.
+ msg.oneofMessage.optionalInt32 = 200
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default
+ XCTAssertTrue(msg.oneofMessage === autoCreated) // Still the same
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(200))
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofMessage)
+
+ // Clear the oneof.
+ Message3_ClearOOneOfCase(msg)
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oneofFloat, Float(0.0)) // Default
+ XCTAssertEqual(msg.oneofEnum, Message3_Enum.Foo) // Default
+ let autoCreated2 = msg.oneofMessage // Default create one
+ XCTAssertNotNil(autoCreated2)
+ XCTAssertTrue(autoCreated2 !== autoCreated) // New instance
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+
+ msg.oneofInt32 = 10
+ XCTAssertEqual(msg.oneofInt32, Int32(10))
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofInt32)
+
+ // Confirm Message.clear() handles the oneof correctly.
+ msg.clear()
+ XCTAssertEqual(msg.oneofInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+
+ // Sets via the autocreated instance.
+ msg.oneofMessage.optionalInt32 = 300
+ XCTAssertTrue(msg.oneofMessage !== autoCreated) // New instance
+ XCTAssertTrue(msg.oneofMessage !== autoCreated2) // New instance
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(300))
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.OneofMessage)
+
+ // Set message to nil clears the oneof.
+ msg.oneofMessage = nil
+ XCTAssertEqual(msg.oneofMessage.optionalInt32, Int32(0)) // Default
+ XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase.GPBUnsetOneOfCase)
+ }
+
+ func testSerialization() {
+ let msg = Message2()
+
+ msg.optionalInt32 = 100
+ msg.optionalInt64 = 101
+ msg.optionalGroup.a = 102
+ msg.repeatedStringArray.addObject("abc")
+ msg.repeatedStringArray.addObject("def")
+
+ let data = msg.data()
+
+ let msg2 = Message2(data: data)
+ XCTAssertTrue(msg2 !== msg) // New instance
+ XCTAssertEqual(msg.optionalInt32, Int32(100))
+ XCTAssertEqual(msg.optionalInt64, Int64(101))
+ XCTAssertEqual(msg.optionalGroup.a, Int32(102))
+ XCTAssertEqual(msg.repeatedStringArray.count, Int(2))
+ XCTAssertEqual(msg2, msg)
+ }
+
+}
diff --git a/objectivec/Tests/GPBTestUtilities.h b/objectivec/Tests/GPBTestUtilities.h
new file mode 100644
index 00000000..37e30f96
--- /dev/null
+++ b/objectivec/Tests/GPBTestUtilities.h
@@ -0,0 +1,87 @@
+// 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>
+
+@class TestAllExtensions;
+@class TestAllTypes;
+@class TestMap;
+@class TestPackedTypes;
+@class TestPackedExtensions;
+@class GPBExtensionRegistry;
+
+// The number of repetitions of any repeated objects inside of test messages.
+extern const uint32_t kGPBDefaultRepeatCount;
+
+@interface GPBTestCase : XCTestCase
+
+- (void)setAllFields:(TestAllTypes *)message repeatedCount:(uint32_t)count;
+- (void)clearAllFields:(TestAllTypes *)message;
+- (void)setAllExtensions:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count;
+- (void)setPackedFields:(TestPackedTypes *)message
+ repeatedCount:(uint32_t)count;
+- (void)setPackedExtensions:(TestPackedExtensions *)message
+ repeatedCount:(uint32_t)count;
+- (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count;
+
+- (TestAllTypes *)allSetRepeatedCount:(uint32_t)count;
+- (TestAllExtensions *)allExtensionsSetRepeatedCount:(uint32_t)count;
+- (TestPackedTypes *)packedSetRepeatedCount:(uint32_t)count;
+- (TestPackedExtensions *)packedExtensionsSetRepeatedCount:(uint32_t)count;
+
+- (void)assertAllFieldsSet:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertAllExtensionsSet:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertRepeatedFieldsModified:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertRepeatedExtensionsModified:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertExtensionsClear:(TestAllExtensions *)message;
+- (void)assertClear:(TestAllTypes *)message;
+- (void)assertPackedFieldsSet:(TestPackedTypes *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertPackedExtensionsSet:(TestPackedExtensions *)message
+ repeatedCount:(uint32_t)count;
+
+- (void)modifyRepeatedExtensions:(TestAllExtensions *)message;
+- (void)modifyRepeatedFields:(TestAllTypes *)message;
+
+- (GPBExtensionRegistry *)extensionRegistry;
+
+- (NSData *)getDataFileNamed:(NSString *)name dataToWrite:(NSData *)dataToWrite;
+
+- (void)assertAllFieldsKVCMatch:(TestAllTypes *)message;
+- (void)setAllFieldsViaKVC:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count;
+- (void)assertClearKVC:(TestAllTypes *)message;
+
+@end
diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m
new file mode 100644
index 00000000..d664a88a
--- /dev/null
+++ b/objectivec/Tests/GPBTestUtilities.m
@@ -0,0 +1,2350 @@
+// 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 "GPBTestUtilities.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+const uint32_t kGPBDefaultRepeatCount = 2;
+
+// Small category to easily turn a CString into an NSData.
+@interface NSData (GPBTestCase)
++ (NSData *)gpbtu_dataWithCString:(char *)buffer;
++ (instancetype)gpbtu_dataWithEmbeddedNulls;
+@end
+
+@implementation NSData (GPBTestCase)
++ (NSData *)gpbtu_dataWithCString:(char *)buffer {
+ return [NSData dataWithBytes:buffer length:strlen(buffer)];
+}
+
++ (instancetype)gpbtu_dataWithUint32:(uint32_t)value {
+ return [[[self alloc] initWithUint32_gpbtu:value] autorelease];
+}
+
+- (instancetype)initWithUint32_gpbtu:(uint32_t)value {
+ value = CFSwapInt32HostToLittle(value);
+ return [self initWithBytes:&value length:sizeof(value)];
+}
+
++ (instancetype)gpbtu_dataWithEmbeddedNulls {
+ char bytes[6] = "\1\0\2\3\0\5";
+ return [self dataWithBytes:bytes length:sizeof(bytes)];
+}
+@end
+
+@implementation GPBTestCase
+
+// Return data for name. Optionally (based on #if setting) write out dataToWrite
+// to replace that data. Useful for setting golden masters.
+- (NSData *)getDataFileNamed:(NSString *)name
+ dataToWrite:(NSData *)dataToWrite {
+ NSBundle *bundle = [NSBundle bundleForClass:[self class]];
+ NSString *path = [bundle pathForResource:[name stringByDeletingPathExtension]
+ ofType:[name pathExtension]];
+ XCTAssertNotNil(path, @"Unable to find %@", name);
+ NSData *data = [NSData dataWithContentsOfFile:path];
+ XCTAssertNotNil(data, @"Unable to load from %@", path);
+#if 0
+ // Enable to write out golden master files.
+ if (!path) {
+ path = [[bundle resourcePath] stringByAppendingPathComponent:name];
+ }
+ NSError *error = nil;
+ BOOL wrote = [dataToWrite writeToFile:path options:NSDataWritingAtomic error:&error];
+ XCTAssertTrue(wrote, @"Unable to write %@ (%@)", path, error);
+ NSLog(@"Wrote data file to %@", path);
+#else
+ // Kill off the unused variable warning.
+ dataToWrite = dataToWrite;
+#endif
+ return data;
+}
+
+// -------------------------------------------------------------------
+
+- (void)modifyRepeatedExtensions:(TestAllExtensions *)message {
+ [message setExtension:[UnittestRoot repeatedInt32Extension]
+ index:1
+ value:@501];
+ [message setExtension:[UnittestRoot repeatedInt64Extension]
+ index:1
+ value:@502];
+ [message setExtension:[UnittestRoot repeatedUint32Extension]
+ index:1
+ value:@503];
+ [message setExtension:[UnittestRoot repeatedUint64Extension]
+ index:1
+ value:@504];
+ [message setExtension:[UnittestRoot repeatedSint32Extension]
+ index:1
+ value:@505];
+ [message setExtension:[UnittestRoot repeatedSint64Extension]
+ index:1
+ value:@506];
+ [message setExtension:[UnittestRoot repeatedFixed32Extension]
+ index:1
+ value:@507];
+ [message setExtension:[UnittestRoot repeatedFixed64Extension]
+ index:1
+ value:@508];
+ [message setExtension:[UnittestRoot repeatedSfixed32Extension]
+ index:1
+ value:@509];
+ [message setExtension:[UnittestRoot repeatedSfixed64Extension]
+ index:1
+ value:@510];
+ [message setExtension:[UnittestRoot repeatedFloatExtension]
+ index:1
+ value:@511.0f];
+ [message setExtension:[UnittestRoot repeatedDoubleExtension]
+ index:1
+ value:@512.0];
+ [message setExtension:[UnittestRoot repeatedBoolExtension]
+ index:1
+ value:@YES];
+ [message setExtension:[UnittestRoot repeatedStringExtension]
+ index:1
+ value:@"515"];
+ [message setExtension:[UnittestRoot repeatedBytesExtension]
+ index:1
+ value:[NSData gpbtu_dataWithUint32:516]];
+
+ RepeatedGroup_extension *repeatedGroup = [RepeatedGroup_extension message];
+ [repeatedGroup setA:517];
+ [message setExtension:[UnittestRoot repeatedGroupExtension]
+ index:1
+ value:repeatedGroup];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ [nestedMessage setBb:518];
+ [message setExtension:[UnittestRoot repeatedNestedMessageExtension]
+ index:1
+ value:nestedMessage];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setC:519];
+ [message setExtension:[UnittestRoot repeatedForeignMessageExtension]
+ index:1
+ value:foreignMessage];
+ ImportMessage *importMessage = [ImportMessage message];
+ [importMessage setD:520];
+ [message setExtension:[UnittestRoot repeatedImportMessageExtension]
+ index:1
+ value:importMessage];
+
+ [message setExtension:[UnittestRoot repeatedNestedEnumExtension]
+ index:1
+ value:@(TestAllTypes_NestedEnum_Foo)];
+ [message setExtension:[UnittestRoot repeatedForeignEnumExtension]
+ index:1
+ value:@(ForeignEnum_ForeignFoo)];
+ [message setExtension:[UnittestRoot repeatedImportEnumExtension]
+ index:1
+ value:@(ImportEnum_ImportFoo)];
+
+ [message setExtension:[UnittestRoot repeatedStringPieceExtension]
+ index:1
+ value:@"524"];
+ [message setExtension:[UnittestRoot repeatedCordExtension]
+ index:1
+ value:@"525"];
+}
+
+- (void)assertAllExtensionsSet:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count {
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalUint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalUint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalSint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalSint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalFixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalFixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalSfixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalSfixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalFloatExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalDoubleExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalBoolExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalStringExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalBytesExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+
+ XCTAssertTrue([[message getExtension:[UnittestRoot optionalGroupExtension]] hasA]);
+ XCTAssertTrue([[message getExtension:[UnittestRoot optionalNestedMessageExtension]] hasBb]);
+ XCTAssertTrue([[message getExtension:[UnittestRoot optionalForeignMessageExtension]] hasC]);
+ XCTAssertTrue([[message getExtension:[UnittestRoot optionalImportMessageExtension]] hasD]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalNestedEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalForeignEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalImportEnumExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalStringPieceExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot optionalCordExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFloatExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultDoubleExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultBoolExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultBytesExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultNestedEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultForeignEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultImportEnumExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringPieceExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultCordExtension]]);
+
+ XCTAssertEqual(101, [[message getExtension:[UnittestRoot optionalInt32Extension]] intValue]);
+ XCTAssertEqual(102LL, [[message getExtension:[UnittestRoot optionalInt64Extension]] longLongValue]);
+ XCTAssertEqual(103U, [[message getExtension:[UnittestRoot optionalUint32Extension]] unsignedIntValue]);
+ XCTAssertEqual(104ULL, [[message getExtension:[UnittestRoot optionalUint64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(105, [[message getExtension:[UnittestRoot optionalSint32Extension]] intValue]);
+ XCTAssertEqual(106LL, [[message getExtension:[UnittestRoot optionalSint64Extension]] longLongValue]);
+ XCTAssertEqual(107U, [[message getExtension:[UnittestRoot optionalFixed32Extension]] unsignedIntValue]);
+ XCTAssertEqual(108ULL, [[message getExtension:[UnittestRoot optionalFixed64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(109, [[message getExtension:[UnittestRoot optionalSfixed32Extension]] intValue]);
+ XCTAssertEqual(110LL, [[message getExtension:[UnittestRoot optionalSfixed64Extension]] longLongValue]);
+ XCTAssertEqualWithAccuracy(111.0f, [[message getExtension:[UnittestRoot optionalFloatExtension]] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy(112.0, [[message getExtension:[UnittestRoot optionalDoubleExtension]] doubleValue], 0.01);
+ XCTAssertTrue([[message getExtension:[UnittestRoot optionalBoolExtension]] boolValue]);
+ XCTAssertEqualObjects(@"115", [message getExtension:[UnittestRoot optionalStringExtension]]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithEmbeddedNulls], [message getExtension:[UnittestRoot optionalBytesExtension]]);
+
+ XCTAssertEqual(117, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot optionalGroupExtension]] a]);
+ XCTAssertEqual(118, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot optionalNestedMessageExtension]] bb]);
+ XCTAssertEqual(119, [[message getExtension:[UnittestRoot optionalForeignMessageExtension]] c]);
+ XCTAssertEqual(120, [[message getExtension:[UnittestRoot optionalImportMessageExtension]] d]);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Baz, [[message getExtension:[UnittestRoot optionalNestedEnumExtension]] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignBaz, [[message getExtension:[UnittestRoot optionalForeignEnumExtension]] intValue]);
+ XCTAssertEqual(ImportEnum_ImportBaz, [[message getExtension:[UnittestRoot optionalImportEnumExtension]] intValue]);
+
+ XCTAssertEqualObjects(@"124", [message getExtension:[UnittestRoot optionalStringPieceExtension]]);
+ XCTAssertEqualObjects(@"125", [message getExtension:[UnittestRoot optionalCordExtension]]);
+
+ // -----------------------------------------------------------------
+
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFloatExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedDoubleExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBoolExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
+
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
+
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringPieceExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedCordExtension]] count]);
+
+ for (uint32_t i = 0; i < count; ++i) {
+ id extension = [message getExtension:[UnittestRoot repeatedInt32Extension]];
+ XCTAssertEqual((int)(201 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot repeatedInt64Extension]];
+ XCTAssertEqual(202 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot repeatedUint32Extension]];
+ XCTAssertEqual(203 + i * 100, [extension[i] unsignedIntValue]);
+ extension = [message getExtension:[UnittestRoot repeatedUint64Extension]];
+ XCTAssertEqual(204 + i * 100, [extension[i] unsignedLongLongValue]);
+ extension = [message getExtension:[UnittestRoot repeatedSint32Extension]];
+ XCTAssertEqual((int)(205 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot repeatedSint64Extension]];
+ XCTAssertEqual(206 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot repeatedFixed32Extension]];
+ XCTAssertEqual(207 + i * 100, [extension[i] unsignedIntValue]);
+ extension = [message getExtension:[UnittestRoot repeatedFixed64Extension]];
+ XCTAssertEqual(208 + i * 100, [extension[i] unsignedLongLongValue]);
+ extension = [message getExtension:[UnittestRoot repeatedSfixed32Extension]];
+ XCTAssertEqual((int)(209 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot repeatedSfixed64Extension]];
+ XCTAssertEqual(210 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot repeatedFloatExtension]];
+ XCTAssertEqualWithAccuracy(211 + i * 100, [extension[i] floatValue], 0.01);
+ extension = [message getExtension:[UnittestRoot repeatedDoubleExtension]];
+ XCTAssertEqualWithAccuracy(212 + i * 100, [extension[i] doubleValue], 0.01);
+ extension = [message getExtension:[UnittestRoot repeatedBoolExtension]];
+ XCTAssertEqual((i % 2) ? YES : NO, [extension[i] boolValue]);
+
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+ extension = [message getExtension:[UnittestRoot repeatedStringExtension]];
+ XCTAssertEqualObjects(string, extension[i]);
+ [string release];
+
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+ extension = [message getExtension:[UnittestRoot repeatedBytesExtension]];
+ XCTAssertEqualObjects(data, extension[i]);
+ [data release];
+
+ extension = [message getExtension:[UnittestRoot repeatedGroupExtension]];
+ XCTAssertEqual((int)(217 + i * 100), [(TestAllTypes_OptionalGroup*)extension[i] a]);
+ extension = [message getExtension:[UnittestRoot repeatedNestedMessageExtension]];
+ XCTAssertEqual((int)(218 + i * 100), [(TestAllTypes_NestedMessage*)extension[i] bb]);
+ extension = [message getExtension:[UnittestRoot repeatedForeignMessageExtension]];
+ XCTAssertEqual((int)(219 + i * 100), [extension[i] c]);
+ extension = [message getExtension:[UnittestRoot repeatedImportMessageExtension]];
+ XCTAssertEqual((int)(220 + i * 100), [extension[i] d]);
+
+ extension = [message getExtension:[UnittestRoot repeatedNestedEnumExtension]];
+ XCTAssertEqual((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz, [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot repeatedForeignEnumExtension]];
+ XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz, [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot repeatedImportEnumExtension]];
+ XCTAssertEqual((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz, [extension[i] intValue]);
+
+ string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+ extension = [message getExtension:[UnittestRoot repeatedStringPieceExtension]];
+ XCTAssertEqualObjects(string, extension[i]);
+ [string release];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+ extension = [message getExtension:[UnittestRoot repeatedCordExtension]];
+ XCTAssertEqualObjects(string, extension[i]);
+ [string release];
+ }
+
+ // -----------------------------------------------------------------
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultInt64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultUint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSint64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed32Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultSfixed64Extension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultFloatExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultDoubleExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultBoolExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultBytesExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultNestedEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultForeignEnumExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultImportEnumExtension]]);
+
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultStringPieceExtension]]);
+ XCTAssertTrue([message hasExtension:[UnittestRoot defaultCordExtension]]);
+
+ XCTAssertEqual(401, [[message getExtension:[UnittestRoot defaultInt32Extension]] intValue]);
+ XCTAssertEqual(402LL, [[message getExtension:[UnittestRoot defaultInt64Extension]] longLongValue]);
+ XCTAssertEqual(403U, [[message getExtension:[UnittestRoot defaultUint32Extension]] unsignedIntValue]);
+ XCTAssertEqual(404ULL, [[message getExtension:[UnittestRoot defaultUint64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(405, [[message getExtension:[UnittestRoot defaultSint32Extension]] intValue]);
+ XCTAssertEqual(406LL, [[message getExtension:[UnittestRoot defaultSint64Extension]] longLongValue]);
+ XCTAssertEqual(407U, [[message getExtension:[UnittestRoot defaultFixed32Extension]] unsignedIntValue]);
+ XCTAssertEqual(408ULL, [[message getExtension:[UnittestRoot defaultFixed64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(409, [[message getExtension:[UnittestRoot defaultSfixed32Extension]] intValue]);
+ XCTAssertEqual(410LL,[[message getExtension:[UnittestRoot defaultSfixed64Extension]] longLongValue]);
+ XCTAssertEqualWithAccuracy(411.0f, [[message getExtension:[UnittestRoot defaultFloatExtension]] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy(412.0, [[message getExtension:[UnittestRoot defaultDoubleExtension]] doubleValue], 0.01);
+ XCTAssertFalse([[message getExtension:[UnittestRoot defaultBoolExtension]] boolValue]);
+ XCTAssertEqualObjects(@"415", [message getExtension:[UnittestRoot defaultStringExtension]]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:416], [message getExtension:[UnittestRoot defaultBytesExtension]]);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo, [[message getExtension:[UnittestRoot defaultNestedEnumExtension]] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignFoo, [[message getExtension:[UnittestRoot defaultForeignEnumExtension]] intValue]);
+ XCTAssertEqual(ImportEnum_ImportFoo, [[message getExtension:[UnittestRoot defaultImportEnumExtension]] intValue]);
+
+ XCTAssertEqualObjects(@"424", [message getExtension:[UnittestRoot defaultStringPieceExtension]]);
+ XCTAssertEqualObjects(@"425", [message getExtension:[UnittestRoot defaultCordExtension]]);
+}
+
+- (void)assertRepeatedExtensionsModified:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedInt64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedUint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedFloatExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedDoubleExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBoolExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
+
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
+
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringPieceExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedCordExtension]] count]);
+
+ XCTAssertEqual(201,[[message getExtension:[UnittestRoot repeatedInt32Extension]][0] intValue]);
+ XCTAssertEqual(202LL, [[message getExtension:[UnittestRoot repeatedInt64Extension]][0] longLongValue]);
+ XCTAssertEqual(203U, [[message getExtension:[UnittestRoot repeatedUint32Extension]][0] unsignedIntValue]);
+ XCTAssertEqual(204ULL, [[message getExtension:[UnittestRoot repeatedUint64Extension]][0] unsignedLongLongValue]);
+ XCTAssertEqual(205, [[message getExtension:[UnittestRoot repeatedSint32Extension]][0] intValue]);
+ XCTAssertEqual(206LL, [[message getExtension:[UnittestRoot repeatedSint64Extension]][0] longLongValue]);
+ XCTAssertEqual(207U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]][0] unsignedIntValue]);
+ XCTAssertEqual(208ULL, [[message getExtension:[UnittestRoot repeatedFixed64Extension]][0] unsignedLongLongValue]);
+ XCTAssertEqual(209, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]][0] intValue]);
+ XCTAssertEqual(210LL, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]][0] longLongValue]);
+ XCTAssertEqualWithAccuracy(211.0f, [[message getExtension:[UnittestRoot repeatedFloatExtension]][0] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy(212.0, [[message getExtension:[UnittestRoot repeatedDoubleExtension]][0] doubleValue], 0.01);
+ XCTAssertFalse([[message getExtension:[UnittestRoot repeatedBoolExtension]][0] boolValue]);
+ XCTAssertEqualObjects(@"215", [message getExtension:[UnittestRoot repeatedStringExtension]][0]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:216], [message getExtension:[UnittestRoot repeatedBytesExtension]][0]);
+
+ XCTAssertEqual(217, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot repeatedGroupExtension]][0] a]);
+ XCTAssertEqual(218, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot repeatedNestedMessageExtension]][0] bb]);
+ XCTAssertEqual(219, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]][0] c]);
+ XCTAssertEqual(220, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]][0] d]);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Baz,
+ [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]][0] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignBaz,
+ [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]][0] intValue]);
+ XCTAssertEqual(ImportEnum_ImportBaz,
+ [[message getExtension:[UnittestRoot repeatedImportEnumExtension]][0] intValue]);
+
+ XCTAssertEqualObjects(@"224", [message getExtension:[UnittestRoot repeatedStringPieceExtension]][0]);
+ XCTAssertEqualObjects(@"225", [message getExtension:[UnittestRoot repeatedCordExtension]][0]);
+
+ // Actually verify the second (modified) elements now.
+ XCTAssertEqual(501, [[message getExtension:[UnittestRoot repeatedInt32Extension]][1] intValue]);
+ XCTAssertEqual(502LL, [[message getExtension:[UnittestRoot repeatedInt64Extension]][1] longLongValue]);
+ XCTAssertEqual(503U, [[message getExtension:[UnittestRoot repeatedUint32Extension]][1] unsignedIntValue]);
+ XCTAssertEqual(504ULL, [[message getExtension:[UnittestRoot repeatedUint64Extension]][1] unsignedLongLongValue]);
+ XCTAssertEqual(505, [[message getExtension:[UnittestRoot repeatedSint32Extension]][1] intValue]);
+ XCTAssertEqual(506LL, [[message getExtension:[UnittestRoot repeatedSint64Extension]][1] longLongValue]);
+ XCTAssertEqual(507U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]][1] unsignedIntValue]);
+ XCTAssertEqual(508ULL, [[message getExtension:[UnittestRoot repeatedFixed64Extension]][1] unsignedLongLongValue]);
+ XCTAssertEqual(509, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]][1] intValue]);
+ XCTAssertEqual(510LL, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]][1] longLongValue]);
+ XCTAssertEqualWithAccuracy(511.0f, [[message getExtension:[UnittestRoot repeatedFloatExtension]][1] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy(512.0, [[message getExtension:[UnittestRoot repeatedDoubleExtension]][1] doubleValue], 0.01);
+ XCTAssertTrue([[message getExtension:[UnittestRoot repeatedBoolExtension]][1] boolValue]);
+ XCTAssertEqualObjects(@"515", [message getExtension:[UnittestRoot repeatedStringExtension]][1]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:516], [message getExtension:[UnittestRoot repeatedBytesExtension]][1]);
+
+ XCTAssertEqual(517, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot repeatedGroupExtension]][1] a]);
+ XCTAssertEqual(518, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot repeatedNestedMessageExtension]][1] bb]);
+ XCTAssertEqual(519, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]][1] c]);
+ XCTAssertEqual(520, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]][1] d]);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo,
+ [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]][1] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignFoo,
+ [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]][1] intValue]);
+ XCTAssertEqual(ImportEnum_ImportFoo,
+ [[message getExtension:[UnittestRoot repeatedImportEnumExtension]][1] intValue]);
+
+ XCTAssertEqualObjects(@"524", [message getExtension:[UnittestRoot repeatedStringPieceExtension]][1]);
+ XCTAssertEqualObjects(@"525", [message getExtension:[UnittestRoot repeatedCordExtension]][1]);
+}
+
+// -------------------------------------------------------------------
+
+- (void)assertAllFieldsSet:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count {
+ XCTAssertTrue(message.hasOptionalInt32);
+ XCTAssertTrue(message.hasOptionalInt64);
+ XCTAssertTrue(message.hasOptionalUint32);
+ XCTAssertTrue(message.hasOptionalUint64);
+ XCTAssertTrue(message.hasOptionalSint32);
+ XCTAssertTrue(message.hasOptionalSint64);
+ XCTAssertTrue(message.hasOptionalFixed32);
+ XCTAssertTrue(message.hasOptionalFixed64);
+ XCTAssertTrue(message.hasOptionalSfixed32);
+ XCTAssertTrue(message.hasOptionalSfixed64);
+ XCTAssertTrue(message.hasOptionalFloat);
+ XCTAssertTrue(message.hasOptionalDouble);
+ XCTAssertTrue(message.hasOptionalBool);
+ XCTAssertTrue(message.hasOptionalString);
+ XCTAssertTrue(message.hasOptionalBytes);
+
+ XCTAssertTrue(message.hasOptionalGroup);
+ XCTAssertTrue(message.hasOptionalNestedMessage);
+ XCTAssertTrue(message.hasOptionalForeignMessage);
+ XCTAssertTrue(message.hasOptionalImportMessage);
+
+ XCTAssertTrue(message.optionalGroup.hasA);
+ XCTAssertTrue(message.optionalNestedMessage.hasBb);
+ XCTAssertTrue(message.optionalForeignMessage.hasC);
+ XCTAssertTrue(message.optionalImportMessage.hasD);
+
+ XCTAssertTrue(message.hasOptionalNestedEnum);
+ XCTAssertTrue(message.hasOptionalForeignEnum);
+ XCTAssertTrue(message.hasOptionalImportEnum);
+
+ XCTAssertTrue(message.hasOptionalStringPiece);
+ XCTAssertTrue(message.hasOptionalCord);
+
+ XCTAssertEqual(101, message.optionalInt32);
+ XCTAssertEqual(102LL, message.optionalInt64);
+ XCTAssertEqual(103U, message.optionalUint32);
+ XCTAssertEqual(104ULL, message.optionalUint64);
+ XCTAssertEqual(105, message.optionalSint32);
+ XCTAssertEqual(106LL, message.optionalSint64);
+ XCTAssertEqual(107U, message.optionalFixed32);
+ XCTAssertEqual(108ULL, message.optionalFixed64);
+ XCTAssertEqual(109, message.optionalSfixed32);
+ XCTAssertEqual(110LL, message.optionalSfixed64);
+ XCTAssertEqualWithAccuracy(111.0f, message.optionalFloat, 0.1);
+ XCTAssertEqualWithAccuracy(112.0, message.optionalDouble, 0.1);
+ XCTAssertTrue(message.optionalBool);
+ XCTAssertEqualObjects(@"115", message.optionalString);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithEmbeddedNulls],
+ message.optionalBytes);
+
+ XCTAssertEqual(117, message.optionalGroup.a);
+ XCTAssertEqual(118, message.optionalNestedMessage.bb);
+ XCTAssertEqual(119, message.optionalForeignMessage.c);
+ XCTAssertEqual(120, message.optionalImportMessage.d);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Baz, message.optionalNestedEnum);
+ XCTAssertEqual(ForeignEnum_ForeignBaz, message.optionalForeignEnum);
+ XCTAssertEqual(ImportEnum_ImportBaz, message.optionalImportEnum);
+
+ XCTAssertEqualObjects(@"124", message.optionalStringPiece);
+ XCTAssertEqualObjects(@"125", message.optionalCord);
+
+ // -----------------------------------------------------------------
+
+ XCTAssertEqual(count, message.repeatedInt32Array.count);
+ XCTAssertEqual(count, message.repeatedInt64Array.count);
+ XCTAssertEqual(count, message.repeatedUint32Array.count);
+ XCTAssertEqual(count, message.repeatedUint64Array.count);
+ XCTAssertEqual(count, message.repeatedSint32Array.count);
+ XCTAssertEqual(count, message.repeatedSint64Array.count);
+ XCTAssertEqual(count, message.repeatedFixed32Array.count);
+ XCTAssertEqual(count, message.repeatedFixed64Array.count);
+ XCTAssertEqual(count, message.repeatedSfixed32Array.count);
+ XCTAssertEqual(count, message.repeatedSfixed64Array.count);
+ XCTAssertEqual(count, message.repeatedFloatArray.count);
+ XCTAssertEqual(count, message.repeatedDoubleArray.count);
+ XCTAssertEqual(count, message.repeatedBoolArray.count);
+ XCTAssertEqual(count, message.repeatedStringArray.count);
+ XCTAssertEqual(count, message.repeatedBytesArray.count);
+
+ XCTAssertEqual(count, message.repeatedGroupArray.count);
+ XCTAssertEqual(count, message.repeatedNestedMessageArray.count);
+ XCTAssertEqual(count, message.repeatedForeignMessageArray.count);
+ XCTAssertEqual(count, message.repeatedImportMessageArray.count);
+ XCTAssertEqual(count, message.repeatedNestedEnumArray.count);
+ XCTAssertEqual(count, message.repeatedForeignEnumArray.count);
+ XCTAssertEqual(count, message.repeatedImportEnumArray.count);
+
+ XCTAssertEqual(count, message.repeatedStringPieceArray.count);
+ XCTAssertEqual(count, message.repeatedCordArray.count);
+
+ for (uint32_t i = 0; i < count; ++i) {
+ XCTAssertEqual((int)(201 + i * 100),
+ [message.repeatedInt32Array valueAtIndex:i]);
+ XCTAssertEqual(202 + i * 100, [message.repeatedInt64Array valueAtIndex:i]);
+ XCTAssertEqual(203 + i * 100, [message.repeatedUint32Array valueAtIndex:i]);
+ XCTAssertEqual(204 + i * 100, [message.repeatedUint64Array valueAtIndex:i]);
+ XCTAssertEqual((int)(205 + i * 100),
+ [message.repeatedSint32Array valueAtIndex:i]);
+ XCTAssertEqual(206 + i * 100, [message.repeatedSint64Array valueAtIndex:i]);
+ XCTAssertEqual(207 + i * 100,
+ [message.repeatedFixed32Array valueAtIndex:i]);
+ XCTAssertEqual(208 + i * 100,
+ [message.repeatedFixed64Array valueAtIndex:i]);
+ XCTAssertEqual((int)(209 + i * 100),
+ [message.repeatedSfixed32Array valueAtIndex:i]);
+ XCTAssertEqual(210 + i * 100,
+ [message.repeatedSfixed64Array valueAtIndex:i]);
+ XCTAssertEqualWithAccuracy(
+ 211 + i * 100, [message.repeatedFloatArray valueAtIndex:i], 0.1);
+ XCTAssertEqualWithAccuracy(
+ 212 + i * 100, [message.repeatedDoubleArray valueAtIndex:i], 0.1);
+ XCTAssertEqual((i % 2) ? YES : NO,
+ [message.repeatedBoolArray valueAtIndex:i]);
+
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+ XCTAssertEqualObjects(string, message.repeatedStringArray[i]);
+ [string release];
+
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+ XCTAssertEqualObjects(data, message.repeatedBytesArray[i]);
+ [data release];
+
+ XCTAssertEqual((int)(217 + i * 100), ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[i]).a);
+ XCTAssertEqual((int)(218 + i * 100), ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[i]).bb);
+ XCTAssertEqual((int)(219 + i * 100), ((ForeignMessage*)message.repeatedForeignMessageArray[i]).c);
+ XCTAssertEqual((int)(220 + i * 100), ((ImportMessage*)message.repeatedImportMessageArray[i]).d);
+
+ XCTAssertEqual((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz, [message.repeatedNestedEnumArray valueAtIndex:i]);
+ XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz, [message.repeatedForeignEnumArray valueAtIndex:i]);
+ XCTAssertEqual((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz, [message.repeatedImportEnumArray valueAtIndex:i]);
+
+ string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+ XCTAssertEqualObjects(string, message.repeatedStringPieceArray[i]);
+ [string release];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+ XCTAssertEqualObjects(string, message.repeatedCordArray[i]);
+ [string release];
+ }
+
+ // -----------------------------------------------------------------
+
+ XCTAssertTrue(message.hasDefaultInt32);
+ XCTAssertTrue(message.hasDefaultInt64);
+ XCTAssertTrue(message.hasDefaultUint32);
+ XCTAssertTrue(message.hasDefaultUint64);
+ XCTAssertTrue(message.hasDefaultSint32);
+ XCTAssertTrue(message.hasDefaultSint64);
+ XCTAssertTrue(message.hasDefaultFixed32);
+ XCTAssertTrue(message.hasDefaultFixed64);
+ XCTAssertTrue(message.hasDefaultSfixed32);
+ XCTAssertTrue(message.hasDefaultSfixed64);
+ XCTAssertTrue(message.hasDefaultFloat);
+ XCTAssertTrue(message.hasDefaultDouble);
+ XCTAssertTrue(message.hasDefaultBool);
+ XCTAssertTrue(message.hasDefaultString);
+ XCTAssertTrue(message.hasDefaultBytes);
+
+ XCTAssertTrue(message.hasDefaultNestedEnum);
+ XCTAssertTrue(message.hasDefaultForeignEnum);
+ XCTAssertTrue(message.hasDefaultImportEnum);
+
+ XCTAssertTrue(message.hasDefaultStringPiece);
+ XCTAssertTrue(message.hasDefaultCord);
+
+ XCTAssertEqual(401, message.defaultInt32);
+ XCTAssertEqual(402LL, message.defaultInt64);
+ XCTAssertEqual(403U, message.defaultUint32);
+ XCTAssertEqual(404ULL, message.defaultUint64);
+ XCTAssertEqual(405, message.defaultSint32);
+ XCTAssertEqual(406LL, message.defaultSint64);
+ XCTAssertEqual(407U, message.defaultFixed32);
+ XCTAssertEqual(408ULL, message.defaultFixed64);
+ XCTAssertEqual(409, message.defaultSfixed32);
+ XCTAssertEqual(410LL, message.defaultSfixed64);
+ XCTAssertEqualWithAccuracy(411.0f, message.defaultFloat, 0.1);
+ XCTAssertEqualWithAccuracy(412.0, message.defaultDouble, 0.1);
+ XCTAssertFalse(message.defaultBool);
+ XCTAssertEqualObjects(@"415", message.defaultString);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:416],
+ message.defaultBytes);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo, message.defaultNestedEnum);
+ XCTAssertEqual(ForeignEnum_ForeignFoo, message.defaultForeignEnum);
+ XCTAssertEqual(ImportEnum_ImportFoo, message.defaultImportEnum);
+
+ XCTAssertEqualObjects(@"424", message.defaultStringPiece);
+ XCTAssertEqualObjects(@"425", message.defaultCord);
+}
+
+- (void)setAllFields:(TestAllTypes *)message repeatedCount:(uint32_t)count {
+ [message setOptionalInt32:101];
+ [message setOptionalInt64:102];
+ [message setOptionalUint32:103];
+ [message setOptionalUint64:104];
+ [message setOptionalSint32:105];
+ [message setOptionalSint64:106];
+ [message setOptionalFixed32:107];
+ [message setOptionalFixed64:108];
+ [message setOptionalSfixed32:109];
+ [message setOptionalSfixed64:110];
+ [message setOptionalFloat:111];
+ [message setOptionalDouble:112];
+ [message setOptionalBool:YES];
+ [message setOptionalString:@"115"];
+ [message setOptionalBytes:[NSData gpbtu_dataWithEmbeddedNulls]];
+
+ TestAllTypes_OptionalGroup *allTypes = [TestAllTypes_OptionalGroup message];
+ [allTypes setA:117];
+ [message setOptionalGroup:allTypes];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ [nestedMessage setBb:118];
+ [message setOptionalNestedMessage:nestedMessage];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setC:119];
+ [message setOptionalForeignMessage:foreignMessage];
+ ImportMessage *importMessage = [ImportMessage message];
+ [importMessage setD:120];
+ [message setOptionalImportMessage:importMessage];
+
+ [message setOptionalNestedEnum:TestAllTypes_NestedEnum_Baz];
+ [message setOptionalForeignEnum:ForeignEnum_ForeignBaz];
+ [message setOptionalImportEnum:ImportEnum_ImportBaz];
+
+ [message setOptionalStringPiece:@"124"];
+ [message setOptionalCord:@"125"];
+
+ // -----------------------------------------------------------------
+
+ for (uint32_t i = 0; i < count; i++) {
+ [message.repeatedInt32Array addValue:201 + i * 100];
+ [message.repeatedInt64Array addValue:202 + i * 100];
+ [message.repeatedUint32Array addValue:203 + i * 100];
+ [message.repeatedUint64Array addValue:204 + i * 100];
+ [message.repeatedSint32Array addValue:205 + i * 100];
+ [message.repeatedSint64Array addValue:206 + i * 100];
+ [message.repeatedFixed32Array addValue:207 + i * 100];
+ [message.repeatedFixed64Array addValue:208 + i * 100];
+ [message.repeatedSfixed32Array addValue:209 + i * 100];
+ [message.repeatedSfixed64Array addValue:210 + i * 100];
+ [message.repeatedFloatArray addValue:211 + i * 100];
+ [message.repeatedDoubleArray addValue:212 + i * 100];
+ [message.repeatedBoolArray addValue:(i % 2)];
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+ [message.repeatedStringArray addObject:string];
+ [string release];
+
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+ [message.repeatedBytesArray addObject:data];
+ [data release];
+
+ TestAllTypes_RepeatedGroup *testAll =
+ [[TestAllTypes_RepeatedGroup alloc] init];
+ [testAll setA:217 + i * 100];
+ [message.repeatedGroupArray addObject:testAll];
+ [testAll release];
+
+ nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
+ [nestedMessage setBb:218 + i * 100];
+ [message.repeatedNestedMessageArray addObject:nestedMessage];
+ [nestedMessage release];
+
+ foreignMessage = [[ForeignMessage alloc] init];
+ [foreignMessage setC:219 + i * 100];
+ [message.repeatedForeignMessageArray addObject:foreignMessage];
+ [foreignMessage release];
+
+ importMessage = [[ImportMessage alloc] init];
+ [importMessage setD:220 + i * 100];
+ [message.repeatedImportMessageArray addObject:importMessage];
+ [importMessage release];
+
+ [message.repeatedNestedEnumArray addValue:(i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz];
+
+ [message.repeatedForeignEnumArray addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+ [message.repeatedImportEnumArray addValue:(i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+ [message.repeatedStringPieceArray addObject:string];
+ [string release];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+ [message.repeatedCordArray addObject:string];
+ [string release];
+ }
+ // -----------------------------------------------------------------
+
+ message.defaultInt32 = 401;
+ message.defaultInt64 = 402;
+ message.defaultUint32 = 403;
+ message.defaultUint64 = 404;
+ message.defaultSint32 = 405;
+ message.defaultSint64 = 406;
+ message.defaultFixed32 = 407;
+ message.defaultFixed64 = 408;
+ message.defaultSfixed32 = 409;
+ message.defaultSfixed64 = 410;
+ message.defaultFloat = 411;
+ message.defaultDouble = 412;
+ message.defaultBool = NO;
+ message.defaultString = @"415";
+ message.defaultBytes = [NSData gpbtu_dataWithUint32:416];
+
+ message.defaultNestedEnum = TestAllTypes_NestedEnum_Foo;
+ message.defaultForeignEnum = ForeignEnum_ForeignFoo;
+ message.defaultImportEnum = ImportEnum_ImportFoo;
+
+ message.defaultStringPiece = @"424";
+ message.defaultCord = @"425";
+}
+
+- (void)clearAllFields:(TestAllTypes *)message {
+ message.hasOptionalInt32 = NO;
+ message.hasOptionalInt64 = NO;
+ message.hasOptionalUint32 = NO;
+ message.hasOptionalUint64 = NO;
+ message.hasOptionalSint32 = NO;
+ message.hasOptionalSint64 = NO;
+ message.hasOptionalFixed32 = NO;
+ message.hasOptionalFixed64 = NO;
+ message.hasOptionalSfixed32 = NO;
+ message.hasOptionalSfixed64 = NO;
+ message.hasOptionalFloat = NO;
+ message.hasOptionalDouble = NO;
+ message.hasOptionalBool = NO;
+ message.hasOptionalString = NO;
+ message.hasOptionalBytes = NO;
+
+ message.hasOptionalGroup = NO;
+ message.hasOptionalNestedMessage = NO;
+ message.hasOptionalForeignMessage = NO;
+ message.hasOptionalImportMessage = NO;
+
+ message.hasOptionalNestedEnum = NO;
+ message.hasOptionalForeignEnum = NO;
+ message.hasOptionalImportEnum = NO;
+
+ message.hasOptionalStringPiece = NO;
+ message.hasOptionalCord = NO;
+
+ // -----------------------------------------------------------------
+
+ [message.repeatedInt32Array removeAll];
+ [message.repeatedInt64Array removeAll];
+ [message.repeatedUint32Array removeAll];
+ [message.repeatedUint64Array removeAll];
+ [message.repeatedSint32Array removeAll];
+ [message.repeatedSint64Array removeAll];
+ [message.repeatedFixed32Array removeAll];
+ [message.repeatedFixed64Array removeAll];
+ [message.repeatedSfixed32Array removeAll];
+ [message.repeatedSfixed64Array removeAll];
+ [message.repeatedFloatArray removeAll];
+ [message.repeatedDoubleArray removeAll];
+ [message.repeatedBoolArray removeAll];
+ [message.repeatedStringArray removeAllObjects];
+ [message.repeatedBytesArray removeAllObjects];
+
+ [message.repeatedGroupArray removeAllObjects];
+ [message.repeatedNestedMessageArray removeAllObjects];
+ [message.repeatedForeignMessageArray removeAllObjects];
+ [message.repeatedImportMessageArray removeAllObjects];
+
+ [message.repeatedNestedEnumArray removeAll];
+ [message.repeatedForeignEnumArray removeAll];
+ [message.repeatedImportEnumArray removeAll];
+
+ [message.repeatedStringPieceArray removeAllObjects];
+ [message.repeatedCordArray removeAllObjects];
+
+ // -----------------------------------------------------------------
+
+ message.hasDefaultInt32 = NO;
+ message.hasDefaultInt64 = NO;
+ message.hasDefaultUint32 = NO;
+ message.hasDefaultUint64 = NO;
+ message.hasDefaultSint32 = NO;
+ message.hasDefaultSint64 = NO;
+ message.hasDefaultFixed32 = NO;
+ message.hasDefaultFixed64 = NO;
+ message.hasDefaultSfixed32 = NO;
+ message.hasDefaultSfixed64 = NO;
+ message.hasDefaultFloat = NO;
+ message.hasDefaultDouble = NO;
+ message.hasDefaultBool = NO;
+ message.hasDefaultString = NO;
+ message.hasDefaultBytes = NO;
+
+ message.hasDefaultNestedEnum = NO;
+ message.hasDefaultForeignEnum = NO;
+ message.hasDefaultImportEnum = NO;
+
+ message.hasDefaultStringPiece = NO;
+ message.hasDefaultCord = NO;
+}
+
+- (void)setAllExtensions:(TestAllExtensions *)message
+ repeatedCount:(uint32_t)count {
+ [message setExtension:[UnittestRoot optionalInt32Extension] value:@101];
+ [message setExtension:[UnittestRoot optionalInt64Extension] value:@102L];
+ [message setExtension:[UnittestRoot optionalUint32Extension] value:@103];
+ [message setExtension:[UnittestRoot optionalUint64Extension] value:@104L];
+ [message setExtension:[UnittestRoot optionalSint32Extension] value:@105];
+ [message setExtension:[UnittestRoot optionalSint64Extension] value:@106L];
+ [message setExtension:[UnittestRoot optionalFixed32Extension] value:@107];
+ [message setExtension:[UnittestRoot optionalFixed64Extension] value:@108L];
+ [message setExtension:[UnittestRoot optionalSfixed32Extension] value:@109];
+ [message setExtension:[UnittestRoot optionalSfixed64Extension] value:@110L];
+ [message setExtension:[UnittestRoot optionalFloatExtension] value:@111.0f];
+ [message setExtension:[UnittestRoot optionalDoubleExtension] value:@112.0];
+ [message setExtension:[UnittestRoot optionalBoolExtension] value:@YES];
+ [message setExtension:[UnittestRoot optionalStringExtension] value:@"115"];
+ [message setExtension:[UnittestRoot optionalBytesExtension]
+ value:[NSData gpbtu_dataWithEmbeddedNulls]];
+
+ OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message];
+ [optionalGroup setA:117];
+ [message setExtension:[UnittestRoot optionalGroupExtension]
+ value:optionalGroup];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ [nestedMessage setBb:118];
+ [message setExtension:[UnittestRoot optionalNestedMessageExtension]
+ value:nestedMessage];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setC:119];
+ [message setExtension:[UnittestRoot optionalForeignMessageExtension]
+ value:foreignMessage];
+ ImportMessage *importMessage = [ImportMessage message];
+ [importMessage setD:120];
+ [message setExtension:[UnittestRoot optionalImportMessageExtension]
+ value:importMessage];
+
+ [message setExtension:[UnittestRoot optionalNestedEnumExtension]
+ value:@(TestAllTypes_NestedEnum_Baz)];
+ [message setExtension:[UnittestRoot optionalForeignEnumExtension]
+ value:@(ForeignEnum_ForeignBaz)];
+ [message setExtension:[UnittestRoot optionalImportEnumExtension]
+ value:@(ImportEnum_ImportBaz)];
+
+ [message setExtension:[UnittestRoot optionalStringPieceExtension]
+ value:@"124"];
+ [message setExtension:[UnittestRoot optionalCordExtension] value:@"125"];
+
+ for (uint32_t i = 0; i < count; ++i) {
+ [message addExtension:[UnittestRoot repeatedInt32Extension]
+ value:@(201 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedInt64Extension]
+ value:@(202 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedUint32Extension]
+ value:@(203 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedUint64Extension]
+ value:@(204 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedSint32Extension]
+ value:@(205 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedSint64Extension]
+ value:@(206 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedFixed32Extension]
+ value:@(207 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedFixed64Extension]
+ value:@(208 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedSfixed32Extension]
+ value:@(209 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedSfixed64Extension]
+ value:@(210 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedFloatExtension]
+ value:@(211 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedDoubleExtension]
+ value:@(212 + i * 100)];
+ [message addExtension:[UnittestRoot repeatedBoolExtension]
+ value:@((i % 2) ? YES : NO)];
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+ [message addExtension:[UnittestRoot repeatedStringExtension] value:string];
+ [string release];
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+ [message addExtension:[UnittestRoot repeatedBytesExtension] value:data];
+ [data release];
+
+ RepeatedGroup_extension *repeatedGroup =
+ [[RepeatedGroup_extension alloc] init];
+ [repeatedGroup setA:217 + i * 100];
+ [message addExtension:[UnittestRoot repeatedGroupExtension]
+ value:repeatedGroup];
+ [repeatedGroup release];
+ nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
+ [nestedMessage setBb:218 + i * 100];
+ [message addExtension:[UnittestRoot repeatedNestedMessageExtension]
+ value:nestedMessage];
+ [nestedMessage release];
+ foreignMessage = [[ForeignMessage alloc] init];
+ [foreignMessage setC:219 + i * 100];
+ [message addExtension:[UnittestRoot repeatedForeignMessageExtension]
+ value:foreignMessage];
+ [foreignMessage release];
+ importMessage = [[ImportMessage alloc] init];
+ [importMessage setD:220 + i * 100];
+ [message addExtension:[UnittestRoot repeatedImportMessageExtension]
+ value:importMessage];
+ [importMessage release];
+ [message addExtension:[UnittestRoot repeatedNestedEnumExtension]
+ value:@((i % 2) ? TestAllTypes_NestedEnum_Bar
+ : TestAllTypes_NestedEnum_Baz)];
+ [message addExtension:[UnittestRoot repeatedForeignEnumExtension]
+ value:@((i % 2) ? ForeignEnum_ForeignBar
+ : ForeignEnum_ForeignBaz)];
+ [message
+ addExtension:[UnittestRoot repeatedImportEnumExtension]
+ value:@((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz)];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+ [message addExtension:[UnittestRoot repeatedStringPieceExtension]
+ value:string];
+ [string release];
+
+ string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+ [message addExtension:[UnittestRoot repeatedCordExtension] value:string];
+ [string release];
+ }
+
+ // -----------------------------------------------------------------
+
+ [message setExtension:[UnittestRoot defaultInt32Extension] value:@401];
+ [message setExtension:[UnittestRoot defaultInt64Extension] value:@402L];
+ [message setExtension:[UnittestRoot defaultUint32Extension] value:@403];
+ [message setExtension:[UnittestRoot defaultUint64Extension] value:@404L];
+ [message setExtension:[UnittestRoot defaultSint32Extension] value:@405];
+ [message setExtension:[UnittestRoot defaultSint64Extension] value:@406L];
+ [message setExtension:[UnittestRoot defaultFixed32Extension] value:@407];
+ [message setExtension:[UnittestRoot defaultFixed64Extension] value:@408L];
+ [message setExtension:[UnittestRoot defaultSfixed32Extension] value:@409];
+ [message setExtension:[UnittestRoot defaultSfixed64Extension] value:@410L];
+ [message setExtension:[UnittestRoot defaultFloatExtension] value:@411.0f];
+ [message setExtension:[UnittestRoot defaultDoubleExtension] value:@412.0];
+ [message setExtension:[UnittestRoot defaultBoolExtension] value:@NO];
+ [message setExtension:[UnittestRoot defaultStringExtension] value:@"415"];
+ [message setExtension:[UnittestRoot defaultBytesExtension]
+ value:[NSData gpbtu_dataWithUint32:416]];
+
+ [message setExtension:[UnittestRoot defaultNestedEnumExtension]
+ value:@(TestAllTypes_NestedEnum_Foo)];
+ [message setExtension:[UnittestRoot defaultForeignEnumExtension]
+ value:@(ForeignEnum_ForeignFoo)];
+ [message setExtension:[UnittestRoot defaultImportEnumExtension]
+ value:@(ImportEnum_ImportFoo)];
+
+ [message setExtension:[UnittestRoot defaultStringPieceExtension]
+ value:@"424"];
+ [message setExtension:[UnittestRoot defaultCordExtension] value:@"425"];
+}
+
+- (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count {
+ message.mapInt32Int32 = [GPBInt32Int32Dictionary dictionary];
+ message.mapInt64Int64 = [GPBInt64Int64Dictionary dictionary];
+ message.mapUint32Uint32 = [GPBUInt32UInt32Dictionary dictionary];
+ message.mapUint64Uint64 = [GPBUInt64UInt64Dictionary dictionary];
+ message.mapSint32Sint32 = [GPBInt32Int32Dictionary dictionary];
+ message.mapSint64Sint64 = [GPBInt64Int64Dictionary dictionary];
+ message.mapFixed32Fixed32 = [GPBUInt32UInt32Dictionary dictionary];
+ message.mapFixed64Fixed64 = [GPBUInt64UInt64Dictionary dictionary];
+ message.mapSfixed32Sfixed32 = [GPBInt32Int32Dictionary dictionary];
+ message.mapSfixed64Sfixed64 = [GPBInt64Int64Dictionary dictionary];
+ message.mapInt32Float = [GPBInt32FloatDictionary dictionary];
+ message.mapInt32Double = [GPBInt32DoubleDictionary dictionary];
+ message.mapBoolBool = [GPBBoolBoolDictionary dictionary];
+ message.mapStringString = [NSMutableDictionary dictionary];
+ message.mapInt32Bytes = [GPBInt32ObjectDictionary dictionary];
+ message.mapInt32Enum = [GPBInt32EnumDictionary
+ dictionaryWithValidationFunction:MapEnum_IsValidValue];
+ message.mapInt32ForeignMessage = [GPBInt32ObjectDictionary dictionary];
+
+ for (uint32_t i = 0; i < count; i++) {
+ [message.mapInt32Int32 setValue:(i + 1) forKey:100 + i * 100];
+ [message.mapInt64Int64 setValue:(i + 1) forKey:101 + i * 100];
+ [message.mapUint32Uint32 setValue:(i + 1) forKey:102 + i * 100];
+ [message.mapUint64Uint64 setValue:(i + 1) forKey:103 + i * 100];
+ [message.mapSint32Sint32 setValue:(i + 1) forKey:104 + i * 100];
+ [message.mapSint64Sint64 setValue:(i + 1) forKey:105 + i * 100];
+ [message.mapFixed32Fixed32 setValue:(i + 1) forKey:106 + i * 100];
+ [message.mapFixed64Fixed64 setValue:(i + 1) forKey:107 + i * 100];
+ [message.mapSfixed32Sfixed32 setValue:(i + 1) forKey:108 + i * 100];
+ [message.mapSfixed64Sfixed64 setValue:(i + 1) forKey:109 + i * 100];
+ [message.mapInt32Float setValue:(i + 1) forKey:110 + i * 100];
+ [message.mapInt32Double setValue:(i + 1) forKey:111 + i * 100];
+ [message.mapBoolBool setValue:((i % 2) == 1) forKey:((i % 2) == 0)];
+
+ NSString *keyStr = [[NSString alloc] initWithFormat:@"%d", 112 + i * 100];
+ NSString *dataStr = [[NSString alloc] initWithFormat:@"%d", i + 1];
+ [message.mapStringString setObject:dataStr forKey:keyStr];
+ [keyStr release];
+ [dataStr release];
+
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:i + 1];
+ [message.mapInt32Bytes setValue:data forKey:113 + i * 100];
+ [data release];
+
+ [message.mapInt32Enum
+ setValue:(i % 2) ? MapEnum_MapEnumBar : MapEnum_MapEnumBaz
+ forKey:114 + i * 100];
+
+ ForeignMessage *subMsg = [[ForeignMessage alloc] init];
+ subMsg.c = i + 1;
+ [message.mapInt32ForeignMessage setValue:subMsg forKey:115 + i * 100];
+ [subMsg release];
+ }
+}
+
+- (GPBExtensionRegistry *)extensionRegistry {
+ return [UnittestRoot extensionRegistry];
+}
+
+- (TestAllTypes *)allSetRepeatedCount:(uint32_t)count {
+ TestAllTypes *message = [TestAllTypes message];
+ [self setAllFields:message repeatedCount:count];
+ return message;
+}
+
+- (TestAllExtensions *)allExtensionsSetRepeatedCount:(uint32_t)count {
+ TestAllExtensions *message = [TestAllExtensions message];
+ [self setAllExtensions:message repeatedCount:count];
+ return message;
+}
+
+- (TestPackedTypes *)packedSetRepeatedCount:(uint32_t)count {
+ TestPackedTypes *message = [TestPackedTypes message];
+ [self setPackedFields:message repeatedCount:count];
+ return message;
+}
+
+- (TestPackedExtensions *)packedExtensionsSetRepeatedCount:(uint32_t)count {
+ TestPackedExtensions *message = [TestPackedExtensions message];
+ [self setPackedExtensions:message repeatedCount:count];
+ return message;
+}
+
+// -------------------------------------------------------------------
+
+- (void)assertClear:(TestAllTypes *)message {
+ // hasBlah() should initially be NO for all optional fields.
+ XCTAssertFalse(message.hasOptionalInt32);
+ XCTAssertFalse(message.hasOptionalInt64);
+ XCTAssertFalse(message.hasOptionalUint32);
+ XCTAssertFalse(message.hasOptionalUint64);
+ XCTAssertFalse(message.hasOptionalSint32);
+ XCTAssertFalse(message.hasOptionalSint64);
+ XCTAssertFalse(message.hasOptionalFixed32);
+ XCTAssertFalse(message.hasOptionalFixed64);
+ XCTAssertFalse(message.hasOptionalSfixed32);
+ XCTAssertFalse(message.hasOptionalSfixed64);
+ XCTAssertFalse(message.hasOptionalFloat);
+ XCTAssertFalse(message.hasOptionalDouble);
+ XCTAssertFalse(message.hasOptionalBool);
+ XCTAssertFalse(message.hasOptionalString);
+ XCTAssertFalse(message.hasOptionalBytes);
+
+ XCTAssertFalse(message.hasOptionalGroup);
+ XCTAssertFalse(message.hasOptionalNestedMessage);
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ XCTAssertFalse(message.hasOptionalImportMessage);
+
+ XCTAssertFalse(message.hasOptionalNestedEnum);
+ XCTAssertFalse(message.hasOptionalForeignEnum);
+ XCTAssertFalse(message.hasOptionalImportEnum);
+
+ XCTAssertFalse(message.hasOptionalStringPiece);
+ XCTAssertFalse(message.hasOptionalCord);
+
+ // Optional fields without defaults are set to zero or something like it.
+ XCTAssertEqual(0, message.optionalInt32);
+ XCTAssertEqual(0LL, message.optionalInt64);
+ XCTAssertEqual(0U, message.optionalUint32);
+ XCTAssertEqual(0ULL, message.optionalUint64);
+ XCTAssertEqual(0, message.optionalSint32);
+ XCTAssertEqual(0LL, message.optionalSint64);
+ XCTAssertEqual(0U, message.optionalFixed32);
+ XCTAssertEqual(0ULL, message.optionalFixed64);
+ XCTAssertEqual(0, message.optionalSfixed32);
+ XCTAssertEqual(0LL, message.optionalSfixed64);
+ XCTAssertEqual(0.0f, message.optionalFloat);
+ XCTAssertEqual(0.0, message.optionalDouble);
+ XCTAssertFalse(message.optionalBool);
+ XCTAssertEqualObjects(message.optionalString, @"");
+ XCTAssertEqualObjects(message.optionalBytes, GPBEmptyNSData());
+
+ // Embedded messages should also be clear.
+ XCTAssertFalse(message.hasOptionalGroup);
+ XCTAssertFalse(message.hasOptionalNestedMessage);
+ XCTAssertFalse(message.hasOptionalForeignMessage);
+ XCTAssertFalse(message.hasOptionalImportMessage);
+
+ // Enums without defaults are set to the first value in the enum.
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo, message.optionalNestedEnum);
+ XCTAssertEqual(ForeignEnum_ForeignFoo, message.optionalForeignEnum);
+ XCTAssertEqual(ImportEnum_ImportFoo, message.optionalImportEnum);
+
+ XCTAssertEqualObjects(message.optionalStringPiece, @"");
+ XCTAssertEqualObjects(message.optionalCord, @"");
+
+ // Repeated fields are empty.
+ XCTAssertEqual(0U, message.repeatedInt32Array.count);
+ XCTAssertEqual(0U, message.repeatedInt64Array.count);
+ XCTAssertEqual(0U, message.repeatedUint32Array.count);
+ XCTAssertEqual(0U, message.repeatedUint64Array.count);
+ XCTAssertEqual(0U, message.repeatedSint32Array.count);
+ XCTAssertEqual(0U, message.repeatedSint64Array.count);
+ XCTAssertEqual(0U, message.repeatedFixed32Array.count);
+ XCTAssertEqual(0U, message.repeatedFixed64Array.count);
+ XCTAssertEqual(0U, message.repeatedSfixed32Array.count);
+ XCTAssertEqual(0U, message.repeatedSfixed64Array.count);
+ XCTAssertEqual(0U, message.repeatedFloatArray.count);
+ XCTAssertEqual(0U, message.repeatedDoubleArray.count);
+ XCTAssertEqual(0U, message.repeatedBoolArray.count);
+ XCTAssertEqual(0U, message.repeatedStringArray.count);
+ XCTAssertEqual(0U, message.repeatedBytesArray.count);
+
+ XCTAssertEqual(0U, message.repeatedGroupArray.count);
+ XCTAssertEqual(0U, message.repeatedNestedMessageArray.count);
+ XCTAssertEqual(0U, message.repeatedForeignMessageArray.count);
+ XCTAssertEqual(0U, message.repeatedImportMessageArray.count);
+ XCTAssertEqual(0U, message.repeatedNestedEnumArray.count);
+ XCTAssertEqual(0U, message.repeatedForeignEnumArray.count);
+ XCTAssertEqual(0U, message.repeatedImportEnumArray.count);
+
+ XCTAssertEqual(0U, message.repeatedStringPieceArray.count);
+ XCTAssertEqual(0U, message.repeatedCordArray.count);
+
+ // hasBlah() should also be NO for all default fields.
+ XCTAssertFalse(message.hasDefaultInt32);
+ XCTAssertFalse(message.hasDefaultInt64);
+ XCTAssertFalse(message.hasDefaultUint32);
+ XCTAssertFalse(message.hasDefaultUint64);
+ XCTAssertFalse(message.hasDefaultSint32);
+ XCTAssertFalse(message.hasDefaultSint64);
+ XCTAssertFalse(message.hasDefaultFixed32);
+ XCTAssertFalse(message.hasDefaultFixed64);
+ XCTAssertFalse(message.hasDefaultSfixed32);
+ XCTAssertFalse(message.hasDefaultSfixed64);
+ XCTAssertFalse(message.hasDefaultFloat);
+ XCTAssertFalse(message.hasDefaultDouble);
+ XCTAssertFalse(message.hasDefaultBool);
+ XCTAssertFalse(message.hasDefaultString);
+ XCTAssertFalse(message.hasDefaultBytes);
+
+ XCTAssertFalse(message.hasDefaultNestedEnum);
+ XCTAssertFalse(message.hasDefaultForeignEnum);
+ XCTAssertFalse(message.hasDefaultImportEnum);
+
+ XCTAssertFalse(message.hasDefaultStringPiece);
+ XCTAssertFalse(message.hasDefaultCord);
+
+ // Fields with defaults have their default values (duh).
+ XCTAssertEqual(41, message.defaultInt32);
+ XCTAssertEqual(42LL, message.defaultInt64);
+ XCTAssertEqual(43U, message.defaultUint32);
+ XCTAssertEqual(44ULL, message.defaultUint64);
+ XCTAssertEqual(-45, message.defaultSint32);
+ XCTAssertEqual(46LL, message.defaultSint64);
+ XCTAssertEqual(47U, message.defaultFixed32);
+ XCTAssertEqual(48ULL, message.defaultFixed64);
+ XCTAssertEqual(49, message.defaultSfixed32);
+ XCTAssertEqual(-50LL, message.defaultSfixed64);
+ XCTAssertEqualWithAccuracy(51.5f, message.defaultFloat, 0.1);
+ XCTAssertEqualWithAccuracy(52e3, message.defaultDouble, 0.1);
+ XCTAssertTrue(message.defaultBool);
+ XCTAssertEqualObjects(@"hello", message.defaultString);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithCString:"world"],
+ message.defaultBytes);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Bar, message.defaultNestedEnum);
+ XCTAssertEqual(ForeignEnum_ForeignBar, message.defaultForeignEnum);
+ XCTAssertEqual(ImportEnum_ImportBar, message.defaultImportEnum);
+
+ XCTAssertEqualObjects(@"abc", message.defaultStringPiece);
+ XCTAssertEqualObjects(@"123", message.defaultCord);
+}
+
+- (void)assertExtensionsClear:(TestAllExtensions *)message {
+ // hasBlah() should initially be NO for all optional fields.
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalInt32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalInt64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalUint32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalUint64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalSint32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalSint64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalFixed32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalFixed64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalSfixed32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalSfixed64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalFloatExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalDoubleExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalBoolExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalStringExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalBytesExtension]]);
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedEnumExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignEnumExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportEnumExtension]]);
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalStringPieceExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot optionalCordExtension]]);
+
+ // Optional fields without defaults are set to zero or something like it.
+ XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalInt32Extension]] intValue]);
+ XCTAssertEqual(0LL,[[message getExtension:[UnittestRoot optionalInt64Extension]] longLongValue]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot optionalUint32Extension]] unsignedIntValue]);
+ XCTAssertEqual(0ULL, [[message getExtension:[UnittestRoot optionalUint64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalSint32Extension]] intValue]);
+ XCTAssertEqual(0LL, [[message getExtension:[UnittestRoot optionalSint64Extension]] longLongValue]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot optionalFixed32Extension]] unsignedIntValue]);
+ XCTAssertEqual(0ULL, [[message getExtension:[UnittestRoot optionalFixed64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalSfixed32Extension]] intValue]);
+ XCTAssertEqual(0LL, [[message getExtension:[UnittestRoot optionalSfixed64Extension]] longLongValue]);
+ XCTAssertEqualWithAccuracy(0.0f, [[message getExtension:[UnittestRoot optionalFloatExtension]] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy(0.0, [[message getExtension:[UnittestRoot optionalDoubleExtension]] doubleValue], 0.01);
+ XCTAssertFalse([[message getExtension:[UnittestRoot optionalBoolExtension]] boolValue]);
+ XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalStringExtension]]);
+ XCTAssertEqualObjects(GPBEmptyNSData(), [message getExtension:[UnittestRoot optionalBytesExtension]]);
+
+ // Embedded messages should also be clear.
+
+ XCTAssertFalse([[message getExtension:[UnittestRoot optionalGroupExtension]] hasA]);
+ XCTAssertFalse([[message getExtension:[UnittestRoot optionalNestedMessageExtension]] hasBb]);
+ XCTAssertFalse([[message getExtension:[UnittestRoot optionalForeignMessageExtension]] hasC]);
+ XCTAssertFalse([[message getExtension:[UnittestRoot optionalImportMessageExtension]] hasD]);
+
+ XCTAssertEqual(0, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot optionalGroupExtension]] a]);
+ XCTAssertEqual(0, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot optionalNestedMessageExtension]] bb]);
+ XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalForeignMessageExtension]] c]);
+ XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalImportMessageExtension]] d]);
+
+ // Enums without defaults are set to the first value in the enum.
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo,
+ [[message getExtension:[UnittestRoot optionalNestedEnumExtension]] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignFoo,
+ [[message getExtension:[UnittestRoot optionalForeignEnumExtension]] intValue]);
+ XCTAssertEqual(ImportEnum_ImportFoo,
+ [[message getExtension:[UnittestRoot optionalImportEnumExtension]] intValue]);
+
+ XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalStringPieceExtension]]);
+ XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalCordExtension]]);
+
+ // Repeated fields are empty.
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedInt32Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedInt64Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedUint32Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedUint64Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSint32Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSint64Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedFixed64Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedFloatExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedDoubleExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedBoolExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedStringExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
+
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
+
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedStringPieceExtension]] count]);
+ XCTAssertEqual(0U, [[message getExtension:[UnittestRoot repeatedCordExtension]] count]);
+
+ // hasBlah() should also be NO for all default fields.
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultInt32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultInt64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultUint32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultUint64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultSint32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultSint64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultFixed32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultFixed64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultSfixed32Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultSfixed64Extension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultFloatExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultDoubleExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultBoolExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultStringExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultBytesExtension]]);
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultNestedEnumExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultForeignEnumExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultImportEnumExtension]]);
+
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultStringPieceExtension]]);
+ XCTAssertFalse([message hasExtension:[UnittestRoot defaultCordExtension]]);
+
+ // Fields with defaults have their default values (duh).
+ XCTAssertEqual( 41, [[message getExtension:[UnittestRoot defaultInt32Extension]] intValue]);
+ XCTAssertEqual( 42LL, [[message getExtension:[UnittestRoot defaultInt64Extension]] longLongValue]);
+ XCTAssertEqual( 43U, [[message getExtension:[UnittestRoot defaultUint32Extension]] unsignedIntValue]);
+ XCTAssertEqual( 44ULL, [[message getExtension:[UnittestRoot defaultUint64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual(-45, [[message getExtension:[UnittestRoot defaultSint32Extension]] intValue]);
+ XCTAssertEqual( 46LL, [[message getExtension:[UnittestRoot defaultSint64Extension]] longLongValue]);
+ XCTAssertEqual( 47, [[message getExtension:[UnittestRoot defaultFixed32Extension]] intValue]);
+ XCTAssertEqual( 48ULL, [[message getExtension:[UnittestRoot defaultFixed64Extension]] unsignedLongLongValue]);
+ XCTAssertEqual( 49, [[message getExtension:[UnittestRoot defaultSfixed32Extension]] intValue]);
+ XCTAssertEqual(-50LL, [[message getExtension:[UnittestRoot defaultSfixed64Extension]] longLongValue]);
+ XCTAssertEqualWithAccuracy( 51.5f, [[message getExtension:[UnittestRoot defaultFloatExtension]] floatValue], 0.01);
+ XCTAssertEqualWithAccuracy( 52e3, [[message getExtension:[UnittestRoot defaultDoubleExtension]] doubleValue], 0.01);
+ XCTAssertTrue([[message getExtension:[UnittestRoot defaultBoolExtension]] boolValue]);
+ XCTAssertEqualObjects(@"hello", [message getExtension:[UnittestRoot defaultStringExtension]]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithCString:"world"], [message getExtension:[UnittestRoot defaultBytesExtension]]);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Bar,
+ [[message getExtension:[UnittestRoot defaultNestedEnumExtension]] intValue]);
+ XCTAssertEqual(ForeignEnum_ForeignBar,
+ [[message getExtension:[UnittestRoot defaultForeignEnumExtension]] intValue]);
+ XCTAssertEqual(ImportEnum_ImportBar,
+ [[message getExtension:[UnittestRoot defaultImportEnumExtension]] intValue]);
+
+ XCTAssertEqualObjects(@"abc", [message getExtension:[UnittestRoot defaultStringPieceExtension]]);
+ XCTAssertEqualObjects(@"123", [message getExtension:[UnittestRoot defaultCordExtension]]);
+}
+
+- (void)modifyRepeatedFields:(TestAllTypes *)message {
+ [message.repeatedInt32Array replaceValueAtIndex:1 withValue:501];
+ [message.repeatedInt64Array replaceValueAtIndex:1 withValue:502];
+ [message.repeatedUint32Array replaceValueAtIndex:1 withValue:503];
+ [message.repeatedUint64Array replaceValueAtIndex:1 withValue:504];
+ [message.repeatedSint32Array replaceValueAtIndex:1 withValue:505];
+ [message.repeatedSint64Array replaceValueAtIndex:1 withValue:506];
+ [message.repeatedFixed32Array replaceValueAtIndex:1 withValue:507];
+ [message.repeatedFixed64Array replaceValueAtIndex:1 withValue:508];
+ [message.repeatedSfixed32Array replaceValueAtIndex:1 withValue:509];
+ [message.repeatedSfixed64Array replaceValueAtIndex:1 withValue:510];
+ [message.repeatedFloatArray replaceValueAtIndex:1 withValue:511];
+ [message.repeatedDoubleArray replaceValueAtIndex:1 withValue:512];
+ [message.repeatedBoolArray replaceValueAtIndex:1 withValue:YES];
+ [message.repeatedStringArray replaceObjectAtIndex:1 withObject:@"515"];
+
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:516];
+ [message.repeatedBytesArray replaceObjectAtIndex:1 withObject:data];
+ [data release];
+
+ TestAllTypes_RepeatedGroup *testAll =
+ [[TestAllTypes_RepeatedGroup alloc] init];
+ [testAll setA:517];
+ [message.repeatedGroupArray replaceObjectAtIndex:1 withObject:testAll];
+ [testAll release];
+
+ TestAllTypes_NestedMessage *nestedMessage =
+ [[TestAllTypes_NestedMessage alloc] init];
+ [nestedMessage setBb:518];
+ [message.repeatedNestedMessageArray replaceObjectAtIndex:1
+ withObject:nestedMessage];
+ [nestedMessage release];
+
+ ForeignMessage *foreignMessage = [[ForeignMessage alloc] init];
+ [foreignMessage setC:519];
+ [message.repeatedForeignMessageArray replaceObjectAtIndex:1
+ withObject:foreignMessage];
+ [foreignMessage release];
+
+ ImportMessage *importMessage = [[ImportMessage alloc] init];
+ [importMessage setD:520];
+ [message.repeatedImportMessageArray replaceObjectAtIndex:1
+ withObject:importMessage];
+ [importMessage release];
+
+ [message.repeatedNestedEnumArray replaceValueAtIndex:1 withValue:TestAllTypes_NestedEnum_Foo];
+ [message.repeatedForeignEnumArray replaceValueAtIndex:1 withValue:ForeignEnum_ForeignFoo];
+ [message.repeatedImportEnumArray replaceValueAtIndex:1 withValue:ImportEnum_ImportFoo];
+
+ [message.repeatedStringPieceArray replaceObjectAtIndex:1 withObject:@"524"];
+ [message.repeatedCordArray replaceObjectAtIndex:1 withObject:@"525"];
+}
+
+- (void)assertRepeatedFieldsModified:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count {
+ // ModifyRepeatedFields only sets the second repeated element of each
+ // field. In addition to verifying this, we also verify that the first
+ // element and size were *not* modified.
+ XCTAssertEqual(count, message.repeatedInt32Array.count);
+ XCTAssertEqual(count, message.repeatedInt64Array.count);
+ XCTAssertEqual(count, message.repeatedUint32Array.count);
+ XCTAssertEqual(count, message.repeatedUint64Array.count);
+ XCTAssertEqual(count, message.repeatedSint32Array.count);
+ XCTAssertEqual(count, message.repeatedSint64Array.count);
+ XCTAssertEqual(count, message.repeatedFixed32Array.count);
+ XCTAssertEqual(count, message.repeatedFixed64Array.count);
+ XCTAssertEqual(count, message.repeatedSfixed32Array.count);
+ XCTAssertEqual(count, message.repeatedSfixed64Array.count);
+ XCTAssertEqual(count, message.repeatedFloatArray.count);
+ XCTAssertEqual(count, message.repeatedDoubleArray.count);
+ XCTAssertEqual(count, message.repeatedBoolArray.count);
+ XCTAssertEqual(count, message.repeatedStringArray.count);
+ XCTAssertEqual(count, message.repeatedBytesArray.count);
+
+ XCTAssertEqual(count, message.repeatedGroupArray.count);
+ XCTAssertEqual(count, message.repeatedNestedMessageArray.count);
+ XCTAssertEqual(count, message.repeatedForeignMessageArray.count);
+ XCTAssertEqual(count, message.repeatedImportMessageArray.count);
+ XCTAssertEqual(count, message.repeatedNestedEnumArray.count);
+ XCTAssertEqual(count, message.repeatedForeignEnumArray.count);
+ XCTAssertEqual(count, message.repeatedImportEnumArray.count);
+
+ XCTAssertEqual(count, message.repeatedStringPieceArray.count);
+ XCTAssertEqual(count, message.repeatedCordArray.count);
+
+ XCTAssertEqual(201, [message.repeatedInt32Array valueAtIndex:0]);
+ XCTAssertEqual(202LL, [message.repeatedInt64Array valueAtIndex:0]);
+ XCTAssertEqual(203U, [message.repeatedUint32Array valueAtIndex:0]);
+ XCTAssertEqual(204ULL, [message.repeatedUint64Array valueAtIndex:0]);
+ XCTAssertEqual(205, [message.repeatedSint32Array valueAtIndex:0]);
+ XCTAssertEqual(206LL, [message.repeatedSint64Array valueAtIndex:0]);
+ XCTAssertEqual(207U, [message.repeatedFixed32Array valueAtIndex:0]);
+ XCTAssertEqual(208ULL, [message.repeatedFixed64Array valueAtIndex:0]);
+ XCTAssertEqual(209, [message.repeatedSfixed32Array valueAtIndex:0]);
+ XCTAssertEqual(210LL, [message.repeatedSfixed64Array valueAtIndex:0]);
+ XCTAssertEqualWithAccuracy(211.0f, [message.repeatedFloatArray valueAtIndex:0], 0.01);
+ XCTAssertEqualWithAccuracy(212.0, [message.repeatedDoubleArray valueAtIndex:0], 0.01);
+ XCTAssertFalse([message.repeatedBoolArray valueAtIndex:0]);
+ XCTAssertEqualObjects(@"215", message.repeatedStringArray[0]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:216],
+ message.repeatedBytesArray[0]);
+
+ XCTAssertEqual(217, ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[0]).a);
+ XCTAssertEqual(218, ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[0]).bb);
+ XCTAssertEqual(219, ((ForeignMessage*)message.repeatedForeignMessageArray[0]).c);
+ XCTAssertEqual(220, ((ImportMessage*)message.repeatedImportMessageArray[0]).d);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Baz, [message.repeatedNestedEnumArray valueAtIndex:0]);
+ XCTAssertEqual(ForeignEnum_ForeignBaz, [message.repeatedForeignEnumArray valueAtIndex:0]);
+ XCTAssertEqual(ImportEnum_ImportBaz, [message.repeatedImportEnumArray valueAtIndex:0]);
+
+ XCTAssertEqualObjects(@"224", message.repeatedStringPieceArray[0]);
+ XCTAssertEqualObjects(@"225", message.repeatedCordArray[0]);
+
+ // Actually verify the second (modified) elements now.
+ XCTAssertEqual(501, [message.repeatedInt32Array valueAtIndex:1]);
+ XCTAssertEqual(502LL, [message.repeatedInt64Array valueAtIndex:1]);
+ XCTAssertEqual(503U, [message.repeatedUint32Array valueAtIndex:1]);
+ XCTAssertEqual(504ULL, [message.repeatedUint64Array valueAtIndex:1]);
+ XCTAssertEqual(505, [message.repeatedSint32Array valueAtIndex:1]);
+ XCTAssertEqual(506LL, [message.repeatedSint64Array valueAtIndex:1]);
+ XCTAssertEqual(507U, [message.repeatedFixed32Array valueAtIndex:1]);
+ XCTAssertEqual(508ULL, [message.repeatedFixed64Array valueAtIndex:1]);
+ XCTAssertEqual(509, [message.repeatedSfixed32Array valueAtIndex:1]);
+ XCTAssertEqual(510LL, [message.repeatedSfixed64Array valueAtIndex:1]);
+ XCTAssertEqualWithAccuracy(511.0f, [message.repeatedFloatArray valueAtIndex:1], 0.01);
+ XCTAssertEqualWithAccuracy(512.0, [message.repeatedDoubleArray valueAtIndex:1], 0.01);
+ XCTAssertTrue([message.repeatedBoolArray valueAtIndex:1]);
+ XCTAssertEqualObjects(@"515", message.repeatedStringArray[1]);
+ XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:516],
+ message.repeatedBytesArray[1]);
+
+ XCTAssertEqual(517, ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[1]).a);
+ XCTAssertEqual(518, ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[1]).bb);
+ XCTAssertEqual(519, ((ForeignMessage*)message.repeatedForeignMessageArray[1]).c);
+ XCTAssertEqual(520, ((ImportMessage*)message.repeatedImportMessageArray[1]).d);
+
+ XCTAssertEqual(TestAllTypes_NestedEnum_Foo, [message.repeatedNestedEnumArray valueAtIndex:1]);
+ XCTAssertEqual(ForeignEnum_ForeignFoo, [message.repeatedForeignEnumArray valueAtIndex:1]);
+ XCTAssertEqual(ImportEnum_ImportFoo, [message.repeatedImportEnumArray valueAtIndex:1]);
+
+ XCTAssertEqualObjects(@"524", message.repeatedStringPieceArray[1]);
+ XCTAssertEqualObjects(@"525", message.repeatedCordArray[1]);
+}
+
+- (void)setPackedFields:(TestPackedTypes *)message
+ repeatedCount:(uint32_t)count {
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:601 + i * 100];
+ }
+ [message setPackedInt32Array:scratch];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:602 + i * 100];
+ }
+ [message setPackedInt64Array:scratch];
+ }
+ {
+ GPBUInt32Array *scratch = [GPBUInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:603 + i * 100];
+ }
+ [message setPackedUint32Array:scratch];
+ }
+ {
+ GPBUInt64Array *scratch = [GPBUInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:604 + i * 100];
+ }
+ [message setPackedUint64Array:scratch];
+ }
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:605 + i * 100];
+ }
+ [message setPackedSint32Array:scratch];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:606 + i * 100];
+ }
+ [message setPackedSint64Array:scratch];
+ }
+ {
+ GPBUInt32Array *scratch = [GPBUInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:607 + i * 100];
+ }
+ [message setPackedFixed32Array:scratch];
+ }
+ {
+ GPBUInt64Array *scratch = [GPBUInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:608 + i * 100];
+ }
+ [message setPackedFixed64Array:scratch];
+ }
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:609 + i * 100];
+ }
+ [message setPackedSfixed32Array:scratch];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:610 + i * 100];
+ }
+ [message setPackedSfixed64Array:scratch];
+ }
+ {
+ GPBFloatArray *scratch = [GPBFloatArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:611 + i * 100];
+ }
+ [message setPackedFloatArray:scratch];
+ }
+ {
+ GPBDoubleArray *scratch = [GPBDoubleArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:612 + i * 100];
+ }
+ [message setPackedDoubleArray:scratch];
+ }
+ {
+ GPBBoolArray *scratch = [GPBBoolArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:(i % 2) ? YES : NO];
+ }
+ [message setPackedBoolArray:scratch];
+ }
+ {
+ GPBEnumArray *scratch =
+ [GPBEnumArray arrayWithValidationFunction:ForeignEnum_IsValidValue];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch
+ addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+ }
+ [message setPackedEnumArray:scratch];
+ }
+}
+
+- (void)assertPackedFieldsSet:(TestPackedTypes *)message
+ repeatedCount:(uint32_t)count {
+ XCTAssertEqual(count, message.packedInt32Array.count);
+ XCTAssertEqual(count, message.packedInt64Array.count);
+ XCTAssertEqual(count, message.packedUint32Array.count);
+ XCTAssertEqual(count, message.packedUint64Array.count);
+ XCTAssertEqual(count, message.packedSint32Array.count);
+ XCTAssertEqual(count, message.packedSint64Array.count);
+ XCTAssertEqual(count, message.packedFixed32Array.count);
+ XCTAssertEqual(count, message.packedFixed64Array.count);
+ XCTAssertEqual(count, message.packedSfixed32Array.count);
+ XCTAssertEqual(count, message.packedSfixed64Array.count);
+ XCTAssertEqual(count, message.packedFloatArray.count);
+ XCTAssertEqual(count, message.packedDoubleArray.count);
+ XCTAssertEqual(count, message.packedBoolArray.count);
+ XCTAssertEqual(count, message.packedEnumArray.count);
+ for (uint32_t i = 0; i < count; ++i) {
+ XCTAssertEqual((int)(601 + i * 100),
+ [message.packedInt32Array valueAtIndex:i]);
+ XCTAssertEqual(602 + i * 100, [message.packedInt64Array valueAtIndex:i]);
+ XCTAssertEqual(603 + i * 100, [message.packedUint32Array valueAtIndex:i]);
+ XCTAssertEqual(604 + i * 100, [message.packedUint64Array valueAtIndex:i]);
+ XCTAssertEqual((int)(605 + i * 100),
+ [message.packedSint32Array valueAtIndex:i]);
+ XCTAssertEqual(606 + i * 100, [message.packedSint64Array valueAtIndex:i]);
+ XCTAssertEqual(607 + i * 100, [message.packedFixed32Array valueAtIndex:i]);
+ XCTAssertEqual(608 + i * 100, [message.packedFixed64Array valueAtIndex:i]);
+ XCTAssertEqual((int)(609 + i * 100),
+ [message.packedSfixed32Array valueAtIndex:i]);
+ XCTAssertEqual(610 + i * 100, [message.packedSfixed64Array valueAtIndex:i]);
+ XCTAssertEqualWithAccuracy(611 + i * 100,
+ [message.packedFloatArray valueAtIndex:i], 0.01);
+ XCTAssertEqualWithAccuracy(
+ 612 + i * 100, [message.packedDoubleArray valueAtIndex:i], 0.01);
+ XCTAssertEqual((i % 2) ? YES : NO,
+ [message.packedBoolArray valueAtIndex:i]);
+ XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz,
+ [message.packedEnumArray valueAtIndex:i]);
+ }
+}
+
+- (void)setPackedExtensions:(TestPackedExtensions *)message
+ repeatedCount:(uint32_t)count {
+ for (uint32_t i = 0; i < count; i++) {
+ [message addExtension:[UnittestRoot packedInt32Extension]
+ value:@(601 + i * 100)];
+ [message addExtension:[UnittestRoot packedInt64Extension]
+ value:@(602 + i * 100)];
+ [message addExtension:[UnittestRoot packedUint32Extension]
+ value:@(603 + i * 100)];
+ [message addExtension:[UnittestRoot packedUint64Extension]
+ value:@(604 + i * 100)];
+ [message addExtension:[UnittestRoot packedSint32Extension]
+ value:@(605 + i * 100)];
+ [message addExtension:[UnittestRoot packedSint64Extension]
+ value:@(606 + i * 100)];
+ [message addExtension:[UnittestRoot packedFixed32Extension]
+ value:@(607 + i * 100)];
+ [message addExtension:[UnittestRoot packedFixed64Extension]
+ value:@(608 + i * 100)];
+ [message addExtension:[UnittestRoot packedSfixed32Extension]
+ value:@(609 + i * 100)];
+ [message addExtension:[UnittestRoot packedSfixed64Extension]
+ value:@(610 + i * 100)];
+ [message addExtension:[UnittestRoot packedFloatExtension]
+ value:@(611 + i * 100)];
+ [message addExtension:[UnittestRoot packedDoubleExtension]
+ value:@(612 + i * 100)];
+ [message addExtension:[UnittestRoot packedBoolExtension]
+ value:@((i % 2) ? YES : NO)];
+ [message addExtension:[UnittestRoot packedEnumExtension]
+ value:@((i % 2) ? ForeignEnum_ForeignBar
+ : ForeignEnum_ForeignBaz)];
+ }
+}
+
+- (void)assertPackedExtensionsSet:(TestPackedExtensions *)message
+ repeatedCount:(uint32_t)count{
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedUint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedUint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSint32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSint64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedFixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedFixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSfixed32Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedSfixed64Extension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedFloatExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedDoubleExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedBoolExtension]] count]);
+ XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedEnumExtension]] count]);
+
+ for (uint32_t i = 0; i < count; ++i) {
+ id extension = [message getExtension:[UnittestRoot packedInt32Extension]];
+ XCTAssertEqual((int)(601 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot packedInt64Extension]];
+ XCTAssertEqual(602 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot packedUint32Extension]];
+ XCTAssertEqual(603 + i * 100, [extension[i] unsignedIntValue]);
+ extension = [message getExtension:[UnittestRoot packedUint64Extension]];
+ XCTAssertEqual(604 + i * 100, [extension[i] unsignedLongLongValue]);
+ extension = [message getExtension:[UnittestRoot packedSint32Extension]];
+ XCTAssertEqual((int)(605 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot packedSint64Extension]];
+ XCTAssertEqual(606 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot packedFixed32Extension]];
+ XCTAssertEqual(607 + i * 100, [extension[i] unsignedIntValue]);
+ extension = [message getExtension:[UnittestRoot packedFixed64Extension]];
+ XCTAssertEqual(608 + i * 100, [extension[i] unsignedLongLongValue]);
+ extension = [message getExtension:[UnittestRoot packedSfixed32Extension]];
+ XCTAssertEqual((int)(609 + i * 100), [extension[i] intValue]);
+ extension = [message getExtension:[UnittestRoot packedSfixed64Extension]];
+ XCTAssertEqual(610 + i * 100, [extension[i] longLongValue]);
+ extension = [message getExtension:[UnittestRoot packedFloatExtension]];
+ XCTAssertEqualWithAccuracy(611 + i * 100, [extension[i] floatValue], 0.01);
+ extension = [message getExtension:[UnittestRoot packedDoubleExtension]];
+ XCTAssertEqualWithAccuracy(612 + i * 100, [extension[i] doubleValue], 0.01);
+ extension = [message getExtension:[UnittestRoot packedBoolExtension]];
+ XCTAssertEqual((i % 2) ? YES : NO, [extension[i] boolValue]);
+ extension = [message getExtension:[UnittestRoot packedEnumExtension]];
+ XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz,
+ [extension[i] intValue]);
+ }
+}
+
+- (void)assertAllFieldsKVCMatch:(TestAllTypes *)message {
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt32"], @YES);
+ XCTAssertEqualObjects(@(message.optionalInt32), [message valueForKey:@"optionalInt32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt64"], @YES);
+ XCTAssertEqualObjects(@(message.optionalInt64), [message valueForKey:@"optionalInt64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint32"], @YES);
+ XCTAssertEqualObjects(@(message.optionalUint32), [message valueForKey:@"optionalUint32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint64"], @YES);
+ XCTAssertEqualObjects(@(message.optionalUint64), [message valueForKey:@"optionalUint64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint32"], @YES);
+ XCTAssertEqualObjects(@(message.optionalSint32), [message valueForKey:@"optionalSint32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint64"], @YES);
+ XCTAssertEqualObjects(@(message.optionalSint64), [message valueForKey:@"optionalSint64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed32"], @YES);
+ XCTAssertEqualObjects(@(message.optionalFixed32), [message valueForKey:@"optionalFixed32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed64"], @YES);
+ XCTAssertEqualObjects(@(message.optionalFixed64), [message valueForKey:@"optionalFixed64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed32"], @YES);
+ XCTAssertEqualObjects(@(message.optionalSfixed32), [message valueForKey:@"optionalSfixed32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed64"], @YES);
+ XCTAssertEqualObjects(@(message.optionalSfixed64), [message valueForKey:@"optionalSfixed64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFloat"], @YES);
+ XCTAssertEqualObjects(@(message.optionalFloat), [message valueForKey:@"optionalFloat"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalDouble"], @YES);
+ XCTAssertEqualObjects(@(message.optionalDouble), [message valueForKey:@"optionalDouble"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalBool"], @YES);
+ XCTAssertEqualObjects(@(message.optionalBool), [message valueForKey:@"optionalBool"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalString"], @YES);
+ XCTAssertEqualObjects(message.optionalString, [message valueForKey:@"optionalString"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalBytes"], @YES);
+ XCTAssertEqualObjects(message.optionalBytes, [message valueForKey:@"optionalBytes"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalGroup"], @YES);
+ XCTAssertNotNil(message.optionalGroup);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.hasA"], @YES);
+ XCTAssertEqualObjects(@(message.optionalGroup.a), [message valueForKeyPath:@"optionalGroup.a"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedMessage"], @YES);
+ XCTAssertNotNil(message.optionalNestedMessage);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalNestedMessage.hasBb"], @YES);
+ XCTAssertEqualObjects(@(message.optionalNestedMessage.bb), [message valueForKeyPath:@"optionalNestedMessage.bb"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignMessage"], @YES);
+ XCTAssertNotNil(message.optionalForeignMessage);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalForeignMessage.hasC"], @YES);
+ XCTAssertEqualObjects(@(message.optionalForeignMessage.c), [message valueForKeyPath:@"optionalForeignMessage.c"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportMessage"], @YES);
+ XCTAssertNotNil(message.optionalForeignMessage);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.hasD"], @YES);
+ XCTAssertEqualObjects(@(message.optionalImportMessage.d), [message valueForKeyPath:@"optionalImportMessage.d"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedEnum"], @YES);
+ XCTAssertEqualObjects(@(message.optionalNestedEnum), [message valueForKey:@"optionalNestedEnum"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignEnum"], @YES);
+ XCTAssertEqualObjects(@(message.optionalForeignEnum), [message valueForKey:@"optionalForeignEnum"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportEnum"], @YES);
+ XCTAssertEqualObjects(@(message.optionalImportEnum), [message valueForKey:@"optionalImportEnum"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalStringPiece"], @YES);
+ XCTAssertEqualObjects(message.optionalStringPiece, [message valueForKey:@"optionalStringPiece"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalCord"], @YES);
+ XCTAssertEqualObjects(message.optionalCord, [message valueForKey:@"optionalCord"]);
+
+ // -----------------------------------------------------------------
+
+ // GPBArray interface for repeated
+
+ XCTAssertEqualObjects(message.repeatedInt32Array, [message valueForKey:@"repeatedInt32Array"]);
+ XCTAssertEqualObjects(message.repeatedInt64Array, [message valueForKey:@"repeatedInt64Array"]);
+ XCTAssertEqualObjects(message.repeatedUint32Array, [message valueForKey:@"repeatedUint32Array"]);
+ XCTAssertEqualObjects(message.repeatedUint64Array, [message valueForKey:@"repeatedUint64Array"]);
+ XCTAssertEqualObjects(message.repeatedSint32Array, [message valueForKey:@"repeatedSint32Array"]);
+ XCTAssertEqualObjects(message.repeatedSint64Array, [message valueForKey:@"repeatedSint64Array"]);
+ XCTAssertEqualObjects(message.repeatedFixed32Array, [message valueForKey:@"repeatedFixed32Array"]);
+ XCTAssertEqualObjects(message.repeatedFixed64Array, [message valueForKey:@"repeatedFixed64Array"]);
+ XCTAssertEqualObjects(message.repeatedSfixed32Array, [message valueForKey:@"repeatedSfixed32Array"]);
+ XCTAssertEqualObjects(message.repeatedSfixed64Array, [message valueForKey:@"repeatedSfixed64Array"]);
+ XCTAssertEqualObjects(message.repeatedFloatArray, [message valueForKey:@"repeatedFloatArray"]);
+ XCTAssertEqualObjects(message.repeatedDoubleArray, [message valueForKey:@"repeatedDoubleArray"]);
+ XCTAssertEqualObjects(message.repeatedBoolArray, [message valueForKey:@"repeatedBoolArray"]);
+ XCTAssertEqualObjects(message.repeatedStringArray, [message valueForKey:@"repeatedStringArray"]);
+ XCTAssertEqualObjects(message.repeatedBytesArray, [message valueForKey:@"repeatedBytesArray"]);
+
+ XCTAssertEqualObjects(message.repeatedGroupArray, [message valueForKey:@"repeatedGroupArray"]);
+ XCTAssertEqualObjects(message.repeatedNestedMessageArray, [message valueForKey:@"repeatedNestedMessageArray"]);
+ XCTAssertEqualObjects(message.repeatedForeignMessageArray, [message valueForKey:@"repeatedForeignMessageArray"]);
+ XCTAssertEqualObjects(message.repeatedImportMessageArray, [message valueForKey:@"repeatedImportMessageArray"]);
+
+ XCTAssertEqualObjects(message.repeatedNestedEnumArray, [message valueForKey:@"repeatedNestedEnumArray"]);
+ XCTAssertEqualObjects(message.repeatedForeignEnumArray, [message valueForKey:@"repeatedForeignEnumArray"]);
+ XCTAssertEqualObjects(message.repeatedImportEnumArray, [message valueForKey:@"repeatedImportEnumArray"]);
+
+ XCTAssertEqualObjects(message.repeatedStringPieceArray, [message valueForKey:@"repeatedStringPieceArray"]);
+ XCTAssertEqualObjects(message.repeatedCordArray, [message valueForKey:@"repeatedCordArray"]);
+
+ // -----------------------------------------------------------------
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt32"], @YES);
+ XCTAssertEqualObjects(@(message.defaultInt32), [message valueForKey:@"defaultInt32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt64"], @YES);
+ XCTAssertEqualObjects(@(message.defaultInt64), [message valueForKey:@"defaultInt64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint32"], @YES);
+ XCTAssertEqualObjects(@(message.defaultUint32), [message valueForKey:@"defaultUint32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint64"], @YES);
+ XCTAssertEqualObjects(@(message.defaultUint64), [message valueForKey:@"defaultUint64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint32"], @YES);
+ XCTAssertEqualObjects(@(message.defaultSint32), [message valueForKey:@"defaultSint32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint64"], @YES);
+ XCTAssertEqualObjects(@(message.defaultSint64), [message valueForKey:@"defaultSint64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed32"], @YES);
+ XCTAssertEqualObjects(@(message.defaultFixed32), [message valueForKey:@"defaultFixed32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed64"], @YES);
+ XCTAssertEqualObjects(@(message.defaultFixed64), [message valueForKey:@"defaultFixed64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed32"], @YES);
+ XCTAssertEqualObjects(@(message.defaultSfixed32), [message valueForKey:@"defaultSfixed32"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed64"], @YES);
+ XCTAssertEqualObjects(@(message.defaultSfixed64), [message valueForKey:@"defaultSfixed64"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFloat"], @YES);
+ XCTAssertEqualObjects(@(message.defaultFloat), [message valueForKey:@"defaultFloat"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultDouble"], @YES);
+ XCTAssertEqualObjects(@(message.defaultDouble), [message valueForKey:@"defaultDouble"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultBool"], @YES);
+ XCTAssertEqualObjects(@(message.defaultBool), [message valueForKey:@"defaultBool"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultString"], @YES);
+ XCTAssertEqualObjects(message.defaultString, [message valueForKey:@"defaultString"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultBytes"], @YES);
+ XCTAssertEqualObjects(message.defaultBytes, [message valueForKey:@"defaultBytes"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultNestedEnum"], @YES);
+ XCTAssertEqualObjects(@(message.defaultNestedEnum), [message valueForKey:@"defaultNestedEnum"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultForeignEnum"], @YES);
+ XCTAssertEqualObjects(@(message.defaultForeignEnum), [message valueForKey:@"defaultForeignEnum"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultImportEnum"], @YES);
+ XCTAssertEqualObjects(@(message.defaultImportEnum), [message valueForKey:@"defaultImportEnum"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultStringPiece"], @YES);
+ XCTAssertEqualObjects(message.defaultStringPiece, [message valueForKey:@"defaultStringPiece"]);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultCord"], @YES);
+ XCTAssertEqualObjects(message.defaultCord, [message valueForKey:@"defaultCord"]);
+}
+
+- (void)setAllFieldsViaKVC:(TestAllTypes *)message
+ repeatedCount:(uint32_t)count {
+ [message setValue:@101 forKey:@"optionalInt32"];
+ [message setValue:@102 forKey:@"optionalInt64"];
+ [message setValue:@103 forKey:@"optionalUint32"];
+ [message setValue:@104 forKey:@"optionalUint64"];
+ [message setValue:@105 forKey:@"optionalSint32"];
+ [message setValue:@106 forKey:@"optionalSint64"];
+ [message setValue:@107 forKey:@"optionalFixed32"];
+ [message setValue:@108 forKey:@"optionalFixed64"];
+ [message setValue:@109 forKey:@"optionalSfixed32"];
+ [message setValue:@110 forKey:@"optionalSfixed64"];
+ [message setValue:@111 forKey:@"optionalFloat"];
+ [message setValue:@112 forKey:@"optionalDouble"];
+ [message setValue:@YES forKey:@"optionalBool"];
+ [message setValue:@"115" forKey:@"optionalString"];
+ [message setValue:[NSData gpbtu_dataWithEmbeddedNulls]
+ forKey:@"optionalBytes"];
+
+ TestAllTypes_OptionalGroup *allTypes = [TestAllTypes_OptionalGroup message];
+ [allTypes setValue:@117 forKey:@"a"];
+ [message setValue:allTypes forKey:@"optionalGroup"];
+ TestAllTypes_NestedMessage *nestedMessage =
+ [TestAllTypes_NestedMessage message];
+ [nestedMessage setValue:@118 forKey:@"bb"];
+ [message setValue:nestedMessage forKey:@"optionalNestedMessage"];
+ ForeignMessage *foreignMessage = [ForeignMessage message];
+ [foreignMessage setValue:@119 forKey:@"c"];
+ [message setValue:foreignMessage forKey:@"optionalForeignMessage"];
+ ImportMessage *importMessage = [ImportMessage message];
+ [importMessage setValue:@120 forKey:@"d"];
+ [message setValue:importMessage forKey:@"optionalImportMessage"];
+
+ [message setValue:@(TestAllTypes_NestedEnum_Baz)
+ forKey:@"optionalNestedEnum"];
+ [message setValue:@(ForeignEnum_ForeignBaz) forKey:@"optionalForeignEnum"];
+ [message setValue:@(ImportEnum_ImportBaz) forKey:@"optionalImportEnum"];
+
+ [message setValue:@"124" forKey:@"optionalStringPiece"];
+ [message setValue:@"125" forKey:@"optionalCord"];
+
+ // -----------------------------------------------------------------
+
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:201 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedInt32Array"];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:202 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedInt64Array"];
+ }
+ {
+ GPBUInt32Array *scratch = [GPBUInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:203 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedUint32Array"];
+ }
+ {
+ GPBUInt64Array *scratch = [GPBUInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:204 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedUint64Array"];
+ }
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:205 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedSint32Array"];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:206 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedSint64Array"];
+ }
+ {
+ GPBUInt32Array *scratch = [GPBUInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:207 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedFixed32Array"];
+ }
+ {
+ GPBUInt64Array *scratch = [GPBUInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:208 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedFixed64Array"];
+ }
+ {
+ GPBInt32Array *scratch = [GPBInt32Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:209 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedSfixed32Array"];
+ }
+ {
+ GPBInt64Array *scratch = [GPBInt64Array array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:210 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedSfixed64Array"];
+ }
+ {
+ GPBFloatArray *scratch = [GPBFloatArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:211 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedFloatArray"];
+ }
+ {
+ GPBDoubleArray *scratch = [GPBDoubleArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:212 + i * 100];
+ }
+ [message setValue:scratch forKey:@"repeatedDoubleArray"];
+ }
+ {
+ GPBBoolArray *scratch = [GPBBoolArray array];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:(i % 2) ? YES : NO];
+ }
+ [message setValue:scratch forKey:@"repeatedBoolArray"];
+ }
+
+ NSMutableArray *array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
+ [array addObject:string];
+ [string release];
+ }
+ [message setValue:array forKey:@"repeatedStringArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ NSData *data = [[NSData alloc] initWithUint32_gpbtu:216 + i * 100];
+ [array addObject:data];
+ [data release];
+ }
+ [message setValue:array forKey:@"repeatedBytesArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ TestAllTypes_RepeatedGroup *testAll =
+ [[TestAllTypes_RepeatedGroup alloc] init];
+ [testAll setA:217 + i * 100];
+ [array addObject:testAll];
+ [testAll release];
+ }
+ [message setValue:array forKey:@"repeatedGroupArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
+ [nestedMessage setBb:218 + i * 100];
+ [array addObject:nestedMessage];
+ [nestedMessage release];
+ }
+ [message setValue:array forKey:@"repeatedNestedMessageArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ foreignMessage = [[ForeignMessage alloc] init];
+ [foreignMessage setC:219 + i * 100];
+ [array addObject:foreignMessage];
+ [foreignMessage release];
+ }
+ [message setValue:array forKey:@"repeatedForeignMessageArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ importMessage = [[ImportMessage alloc] init];
+ [importMessage setD:220 + i * 100];
+ [array addObject:importMessage];
+ [importMessage release];
+ }
+ [message setValue:array forKey:@"repeatedImportMessageArray"];
+ [array release];
+
+ {
+ GPBEnumArray *scratch = [GPBEnumArray
+ arrayWithValidationFunction:TestAllTypes_NestedEnum_IsValidValue];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:(i % 2) ? TestAllTypes_NestedEnum_Bar
+ : TestAllTypes_NestedEnum_Baz];
+ }
+ [message setValue:scratch forKey:@"repeatedNestedEnumArray"];
+ }
+ {
+ GPBEnumArray *scratch =
+ [GPBEnumArray arrayWithValidationFunction:ForeignEnum_IsValidValue];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch
+ addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+ }
+ [message setValue:scratch forKey:@"repeatedForeignEnumArray"];
+ }
+ {
+ GPBEnumArray *scratch =
+ [GPBEnumArray arrayWithValidationFunction:ImportEnum_IsValidValue];
+ for (uint32_t i = 0; i < count; ++i) {
+ [scratch addValue:(i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz];
+ }
+ [message setValue:scratch forKey:@"repeatedImportEnumArray"];
+ }
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
+ [array addObject:string];
+ [string release];
+ }
+ [message setValue:array forKey:@"repeatedStringPieceArray"];
+ [array release];
+
+ array = [[NSMutableArray alloc] initWithCapacity:count];
+ for (uint32_t i = 0; i < count; ++i) {
+ NSString *string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
+ [array addObject:string];
+ [string release];
+ }
+ [message setValue:array forKey:@"repeatedCordArray"];
+ [array release];
+
+ // -----------------------------------------------------------------
+
+ [message setValue:@401 forKey:@"defaultInt32"];
+ [message setValue:@402 forKey:@"defaultInt64"];
+ [message setValue:@403 forKey:@"defaultUint32"];
+ [message setValue:@404 forKey:@"defaultUint64"];
+ [message setValue:@405 forKey:@"defaultSint32"];
+ [message setValue:@406 forKey:@"defaultSint64"];
+ [message setValue:@407 forKey:@"defaultFixed32"];
+ [message setValue:@408 forKey:@"defaultFixed64"];
+ [message setValue:@409 forKey:@"defaultSfixed32"];
+ [message setValue:@410 forKey:@"defaultSfixed64"];
+ [message setValue:@411 forKey:@"defaultFloat"];
+ [message setValue:@412 forKey:@"defaultDouble"];
+ [message setValue:@NO forKey:@"defaultBool"];
+ [message setValue:@"415" forKey:@"defaultString"];
+ [message setValue:[NSData gpbtu_dataWithUint32:416] forKey:@"defaultBytes"];
+
+ [message setValue:@(TestAllTypes_NestedEnum_Foo) forKey:@"defaultNestedEnum"];
+ [message setValue:@(ForeignEnum_ForeignFoo) forKey:@"defaultForeignEnum"];
+ [message setValue:@(ImportEnum_ImportFoo) forKey:@"defaultImportEnum"];
+
+ [message setValue:@"424" forKey:@"defaultStringPiece"];
+ [message setValue:@"425" forKey:@"defaultCord"];
+}
+
+- (void)assertClearKVC:(TestAllTypes *)message {
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalInt64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalUint64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSint64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFixed64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalSfixed64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalFloat"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalDouble"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalBool"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalString"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalBytes"], @NO);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalGroup"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedMessage"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignMessage"],
+ @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportMessage"], @NO);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedEnum"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignEnum"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportEnum"], @NO);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalStringPiece"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasOptionalCord"], @NO);
+
+ // Optional fields without defaults are set to zero or something like it.
+ XCTAssertEqualObjects([message valueForKey:@"optionalInt32"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalInt64"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalUint32"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalUint64"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalSint32"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalSint64"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalFixed32"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalFixed64"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalSfixed32"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalSfixed64"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalFloat"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalDouble"], @0);
+ XCTAssertEqualObjects([message valueForKey:@"optionalBool"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"optionalString"], @"");
+ XCTAssertEqualObjects([message valueForKey:@"optionalBytes"],
+ GPBEmptyNSData());
+
+ // Embedded messages should also be exist, but be clear.
+ XCTAssertNotNil([message valueForKeyPath:@"optionalGroup"]);
+ XCTAssertNotNil([message valueForKeyPath:@"optionalNestedMessage"]);
+ XCTAssertNotNil([message valueForKeyPath:@"optionalForeignMessage"]);
+ XCTAssertNotNil([message valueForKeyPath:@"optionalImportMessage"]);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.hasA"], @NO);
+ XCTAssertEqualObjects(
+ [message valueForKeyPath:@"optionalNestedMessage.hasBb"], @NO);
+ XCTAssertEqualObjects(
+ [message valueForKeyPath:@"optionalForeignMessage.hasC"], @NO);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.hasD"],
+ @NO);
+
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.a"], @0);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalNestedMessage.bb"],
+ @0);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalForeignMessage.c"],
+ @0);
+ XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.d"],
+ @0);
+
+ // Enums without defaults are set to the first value in the enum.
+ XCTAssertEqualObjects([message valueForKey:@"optionalNestedEnum"],
+ @(TestAllTypes_NestedEnum_Foo));
+ XCTAssertEqualObjects([message valueForKey:@"optionalForeignEnum"],
+ @(ForeignEnum_ForeignFoo));
+ XCTAssertEqualObjects([message valueForKey:@"optionalImportEnum"],
+ @(ImportEnum_ImportFoo));
+
+ XCTAssertEqualObjects([message valueForKey:@"optionalStringPiece"], @"");
+ XCTAssertEqualObjects([message valueForKey:@"optionalCord"], @"");
+
+ // NSArray interface for repeated doesn't have has*, nil means no value.
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultInt64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultUint64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSint64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFixed64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed32"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultSfixed64"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultFloat"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultDouble"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultBool"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultString"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultBytes"], @NO);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultNestedEnum"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultForeignEnum"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultImportEnum"], @NO);
+
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultStringPiece"], @NO);
+ XCTAssertEqualObjects([message valueForKey:@"hasDefaultCord"], @NO);
+
+ // Fields with defaults have their default values (duh).
+ XCTAssertEqualObjects([message valueForKey:@"defaultInt32"], @41);
+ XCTAssertEqualObjects([message valueForKey:@"defaultInt64"], @42);
+ XCTAssertEqualObjects([message valueForKey:@"defaultUint32"], @43);
+ XCTAssertEqualObjects([message valueForKey:@"defaultUint64"], @44);
+ XCTAssertEqualObjects([message valueForKey:@"defaultSint32"], @-45);
+ XCTAssertEqualObjects([message valueForKey:@"defaultSint64"], @46);
+ XCTAssertEqualObjects([message valueForKey:@"defaultFixed32"], @47);
+ XCTAssertEqualObjects([message valueForKey:@"defaultFixed64"], @48);
+ XCTAssertEqualObjects([message valueForKey:@"defaultSfixed32"], @49);
+ XCTAssertEqualObjects([message valueForKey:@"defaultSfixed64"], @-50);
+ XCTAssertEqualObjects([message valueForKey:@"defaultFloat"], @51.5);
+ XCTAssertEqualObjects([message valueForKey:@"defaultDouble"], @52e3);
+ XCTAssertEqualObjects([message valueForKey:@"defaultBool"], @YES);
+ XCTAssertEqualObjects([message valueForKey:@"defaultString"], @"hello");
+ XCTAssertEqualObjects([message valueForKey:@"defaultBytes"],
+ [NSData gpbtu_dataWithCString:"world"]);
+
+ XCTAssertEqualObjects([message valueForKey:@"defaultNestedEnum"],
+ @(TestAllTypes_NestedEnum_Bar));
+ XCTAssertEqualObjects([message valueForKey:@"defaultForeignEnum"],
+ @(ForeignEnum_ForeignBar));
+ XCTAssertEqualObjects([message valueForKey:@"defaultImportEnum"],
+ @(ImportEnum_ImportBar));
+
+ XCTAssertEqualObjects([message valueForKey:@"defaultStringPiece"], @"abc");
+ XCTAssertEqualObjects([message valueForKey:@"defaultCord"], @"123");
+}
+
+@end
diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m
new file mode 100644
index 00000000..2c271bf7
--- /dev/null
+++ b/objectivec/Tests/GPBUnittestProtos.m
@@ -0,0 +1,56 @@
+// 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.
+
+// Collects all the compiled protos into one file and compiles them to make sure
+// the compiler is generating valid code.
+
+#import "google/protobuf/MapProto2Unittest.pbobjc.m"
+#import "google/protobuf/MapUnittest.pbobjc.m"
+#import "google/protobuf/Unittest.pbobjc.m"
+#import "google/protobuf/UnittestCustomOptions.pbobjc.m"
+#import "google/protobuf/UnittestCycle.pbobjc.m"
+#import "google/protobuf/UnittestDropUnknownFields.pbobjc.m"
+#import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.m"
+#import "google/protobuf/UnittestEmpty.pbobjc.m"
+#import "google/protobuf/UnittestEnormousDescriptor.pbobjc.m"
+#import "google/protobuf/UnittestFilter.pbobjc.m"
+#import "google/protobuf/UnittestImport.pbobjc.m"
+#import "google/protobuf/UnittestImportLite.pbobjc.m"
+#import "google/protobuf/UnittestImportPublic.pbobjc.m"
+#import "google/protobuf/UnittestImportPublicLite.pbobjc.m"
+#import "google/protobuf/UnittestLite.pbobjc.m"
+#import "google/protobuf/UnittestMset.pbobjc.m"
+#import "google/protobuf/UnittestNameMangling.pbobjc.m"
+#import "google/protobuf/UnittestNoGenericServices.pbobjc.m"
+#import "google/protobuf/UnittestObjc.pbobjc.m"
+#import "google/protobuf/UnittestOptimizeFor.pbobjc.m"
+#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.m"
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.m"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.m"
diff --git a/objectivec/Tests/GPBUnknownFieldSetTest.m b/objectivec/Tests/GPBUnknownFieldSetTest.m
new file mode 100644
index 00000000..80186088
--- /dev/null
+++ b/objectivec/Tests/GPBUnknownFieldSetTest.m
@@ -0,0 +1,255 @@
+// 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 "GPBTestUtilities.h"
+
+#import "GPBField_PackagePrivate.h"
+#import "GPBUnknownFieldSet_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+
+@interface GPBUnknownFieldSet (GPBUnknownFieldSetTest)
+- (void)getTags:(int32_t*)tags;
+@end
+
+@interface UnknownFieldSetTest : GPBTestCase {
+ @private
+ TestAllTypes* allFields_;
+ NSData* allFieldsData_;
+
+ // An empty message that has been parsed from allFieldsData. So, it has
+ // unknown fields of every type.
+ TestEmptyMessage* emptyMessage_;
+ GPBUnknownFieldSet* unknownFields_;
+}
+
+@end
+
+@implementation UnknownFieldSetTest
+
+- (void)setUp {
+ allFields_ = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+ allFieldsData_ = [allFields_ data];
+ emptyMessage_ = [TestEmptyMessage parseFromData:allFieldsData_];
+ unknownFields_ = emptyMessage_.unknownFields;
+}
+
+- (GPBField*)getField:(int32_t)number {
+ return [unknownFields_ getField:number];
+}
+
+// Constructs a protocol buffer which contains fields with all the same
+// numbers as allFieldsData except that each field is some other wire
+// type.
+- (NSData*)getBizarroData {
+ GPBUnknownFieldSet* bizarroFields =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ NSUInteger count = [unknownFields_ countOfFields];
+ int32_t tags[count];
+ [unknownFields_ getTags:tags];
+ for (NSUInteger i = 0; i < count; ++i) {
+ int32_t tag = tags[i];
+ GPBField* field = [unknownFields_ getField:tag];
+ if (field.varintList.count == 0) {
+ // Original field is not a varint, so use a varint.
+ GPBField* varintField =
+ [[[GPBField alloc] initWithNumber:tag] autorelease];
+ [varintField addVarint:1];
+ [bizarroFields addField:varintField];
+ } else {
+ // Original field *is* a varint, so use something else.
+ GPBField* fixed32Field =
+ [[[GPBField alloc] initWithNumber:tag] autorelease];
+ [fixed32Field addFixed32:1];
+ [bizarroFields addField:fixed32Field];
+ }
+ }
+
+ return [bizarroFields data];
+}
+
+- (void)testSerialize {
+ // Check that serializing the UnknownFieldSet produces the original data
+ // again.
+ NSData* data = [emptyMessage_ data];
+ XCTAssertEqualObjects(allFieldsData_, data);
+}
+
+- (void)testCopyFrom {
+ TestEmptyMessage* message = [TestEmptyMessage message];
+ [message mergeFrom:emptyMessage_];
+
+ XCTAssertEqualObjects(emptyMessage_.data, message.data);
+}
+
+- (void)testMergeFrom {
+ GPBUnknownFieldSet* set1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+ GPBField* field = [[[GPBField alloc] initWithNumber:2] autorelease];
+ [field addVarint:2];
+ [set1 addField:field];
+ field = [[[GPBField alloc] initWithNumber:3] autorelease];
+ [field addVarint:4];
+ [set1 addField:field];
+
+ GPBUnknownFieldSet* set2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+ field = [[[GPBField alloc] initWithNumber:1] autorelease];
+ [field addVarint:1];
+ [set2 addField:field];
+ field = [[[GPBField alloc] initWithNumber:3] autorelease];
+ [field addVarint:3];
+ [set2 addField:field];
+
+ GPBUnknownFieldSet* set3 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+ field = [[[GPBField alloc] initWithNumber:1] autorelease];
+ [field addVarint:1];
+ [set3 addField:field];
+ field = [[[GPBField alloc] initWithNumber:3] autorelease];
+ [field addVarint:4];
+ [set3 addField:field];
+
+ GPBUnknownFieldSet* set4 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+ field = [[[GPBField alloc] initWithNumber:2] autorelease];
+ [field addVarint:2];
+ [set4 addField:field];
+ field = [[[GPBField alloc] initWithNumber:3] autorelease];
+ [field addVarint:3];
+ [set4 addField:field];
+
+ TestEmptyMessage* source1 = [TestEmptyMessage message];
+ [source1 setUnknownFields:set1];
+ TestEmptyMessage* source2 = [TestEmptyMessage message];
+ [source2 setUnknownFields:set2];
+ TestEmptyMessage* source3 = [TestEmptyMessage message];
+ [source3 setUnknownFields:set3];
+ TestEmptyMessage* source4 = [TestEmptyMessage message];
+ [source4 setUnknownFields:set4];
+
+ TestEmptyMessage* destination1 = [TestEmptyMessage message];
+ [destination1 mergeFrom:source1];
+ [destination1 mergeFrom:source2];
+
+ TestEmptyMessage* destination2 = [TestEmptyMessage message];
+ [destination2 mergeFrom:source3];
+ [destination2 mergeFrom:source4];
+
+ XCTAssertEqualObjects(destination1.data, destination2.data);
+}
+
+- (void)testClearMessage {
+ TestEmptyMessage* message = [TestEmptyMessage message];
+ [message mergeFrom:emptyMessage_];
+ [message clear];
+ XCTAssertEqual(message.serializedSize, (size_t)0);
+}
+
+- (void)testParseKnownAndUnknown {
+ // Test mixing known and unknown fields when parsing.
+ GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease];
+ GPBField* field = [[[GPBField alloc] initWithNumber:123456] autorelease];
+ [field addVarint:654321];
+ [fields addField:field];
+
+ NSData* data = fields.data;
+ TestAllTypes* destination = [TestAllTypes parseFromData:data];
+
+ [self assertAllFieldsSet:destination repeatedCount:kGPBDefaultRepeatCount];
+ XCTAssertEqual(destination.unknownFields.countOfFields, (NSUInteger)1);
+
+ GPBField* field2 = [destination.unknownFields getField:123456];
+ XCTAssertEqual(field2.varintList.count, (NSUInteger)1);
+ XCTAssertEqual(654321ULL, [field2.varintList valueAtIndex:0]);
+}
+
+- (void)testWrongTypeTreatedAsUnknown {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing.
+
+ NSData* bizarroData = [self getBizarroData];
+ TestAllTypes* allTypesMessage = [TestAllTypes parseFromData:bizarroData];
+ TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:bizarroData];
+
+ // All fields should have been interpreted as unknown, so the debug strings
+ // should be the same.
+ XCTAssertEqualObjects(emptyMessage.data, allTypesMessage.data);
+}
+
+- (void)testUnknownExtensions {
+ // Make sure fields are properly parsed to the UnknownFieldSet even when
+ // they are declared as extension numbers.
+
+ TestEmptyMessageWithExtensions* message =
+ [TestEmptyMessageWithExtensions parseFromData:allFieldsData_];
+
+ XCTAssertEqual(unknownFields_.countOfFields,
+ message.unknownFields.countOfFields);
+ XCTAssertEqualObjects(allFieldsData_, message.data);
+}
+
+- (void)testWrongExtensionTypeTreatedAsUnknown {
+ // Test that fields of the wrong wire type are treated like unknown fields
+ // when parsing extensions.
+
+ NSData* bizarroData = [self getBizarroData];
+ TestAllExtensions* allExtensionsMessage =
+ [TestAllExtensions parseFromData:bizarroData];
+ TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:bizarroData];
+
+ // All fields should have been interpreted as unknown, so the debug strings
+ // should be the same.
+ XCTAssertEqualObjects(emptyMessage.data, allExtensionsMessage.data);
+}
+
+- (void)testLargeVarint {
+ GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease];
+ GPBField* field = [[[GPBField alloc] initWithNumber:1] autorelease];
+ [field addVarint:0x7FFFFFFFFFFFFFFFL];
+ [fields addField:field];
+
+ NSData* data = [fields data];
+
+ GPBUnknownFieldSet* parsed = [[[GPBUnknownFieldSet alloc] init] autorelease];
+ [parsed mergeFromData:data];
+ GPBField* field2 = [parsed getField:1];
+ XCTAssertEqual(field2.varintList.count, (NSUInteger)1);
+ XCTAssertEqual(0x7FFFFFFFFFFFFFFFULL, [field2.varintList valueAtIndex:0]);
+}
+
+- (void)testMergingFields {
+ GPBField* field1 = [[[GPBField alloc] initWithNumber:1] autorelease];
+ [field1 addVarint:1];
+ [field1 addFixed32:2];
+ [field1 addFixed64:3];
+ [field1 addLengthDelimited:[NSData dataWithBytes:"hello" length:5]];
+ [field1 addGroup:[[unknownFields_ copy] autorelease]];
+ GPBField* field2 = [[[GPBField alloc] initWithNumber:2] autorelease];
+ [field2 mergeFromField:field1];
+ XCTAssertEqualObjects(field1, field2);
+}
+
+@end
diff --git a/objectivec/Tests/GPBUtilitiesTests.m b/objectivec/Tests/GPBUtilitiesTests.m
new file mode 100644
index 00000000..02de0197
--- /dev/null
+++ b/objectivec/Tests/GPBUtilitiesTests.m
@@ -0,0 +1,363 @@
+// 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 "GPBUtilities_PackagePrivate.h"
+
+#import <objc/runtime.h>
+
+#import "GPBTestUtilities.h"
+
+#import "GPBDescriptor.h"
+#import "GPBDescriptor_PackagePrivate.h"
+#import "GPBMessage.h"
+
+#import "google/protobuf/MapUnittest.pbobjc.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestObjc.pbobjc.h"
+
+@interface UtilitiesTests : GPBTestCase
+@end
+
+// Support code for testing
+typedef struct {
+ uint32_t _has_storage_[1];
+ BOOL aBool;
+ int32_t aInt32;
+ uint32_t aUInt32;
+ int64_t aInt64;
+ uint64_t aUInt64;
+ float aFloat;
+ double aDouble;
+ id aObject;
+ BOOL _hasTest;
+ BOOL stopper;
+ BOOL shouldNotBeCounted;
+ GPBInt32Array *anArray;
+} ApplyFunctionsTest_Storage;
+
+@interface ApplyFunctionsTest : GPBMessage
+@property(nonatomic, readwrite) BOOL aBool;
+@property(nonatomic, readwrite) int32_t aInt32;
+@property(nonatomic, readwrite) uint32_t aUInt32;
+@property(nonatomic, readwrite) int64_t aInt64;
+@property(nonatomic, readwrite) uint64_t aUInt64;
+@property(nonatomic, readwrite) float aFloat;
+@property(nonatomic, readwrite) double aDouble;
+@property(nonatomic, readwrite, retain) id aObject;
+@property(nonatomic, readwrite) BOOL _hasTest;
+@property(nonatomic, readwrite) BOOL stopper;
+@property(nonatomic, readwrite) BOOL shouldNotBeCounted;
+@property(nonatomic, readwrite, retain) GPBInt32Array *anArray;
+@end
+
+@implementation ApplyFunctionsTest
+
+@dynamic aBool, aInt32, aUInt32, aInt64, aUInt64, aFloat, aDouble, aObject;
+@dynamic _hasTest, stopper, shouldNotBeCounted, anArray;
+
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+#define FIELD_ENTRY(NAME, INDEX) \
+ { \
+ .name = "a" #NAME, .hasIndex = INDEX, .type = GPBType##NAME, \
+ .offset = offsetof(ApplyFunctionsTest_Storage, a##NAME), \
+ }
+ FIELD_ENTRY(Bool, 1),
+ FIELD_ENTRY(Int32, 2),
+ FIELD_ENTRY(UInt32, 3),
+ FIELD_ENTRY(Int64, 4),
+ FIELD_ENTRY(UInt64, 5),
+ FIELD_ENTRY(Float, 6),
+ FIELD_ENTRY(Double, 7),
+#undef FIELD_ENTRY
+ {
+ .name = "aObject",
+ .type = GPBTypeString,
+ .hasIndex = 8,
+ .offset = offsetof(ApplyFunctionsTest_Storage, aObject),
+ },
+ {
+ .name = "stopper",
+ .type = GPBTypeBool,
+ .hasIndex = 9,
+ .offset = offsetof(ApplyFunctionsTest_Storage, stopper),
+ },
+ {
+ .name = "shouldNotBeCounted",
+ .type = GPBTypeBool,
+ .hasIndex = 10,
+ .offset = offsetof(ApplyFunctionsTest_Storage, shouldNotBeCounted),
+ },
+ {
+ .name = "anArray",
+ .type = GPBTypeInt32,
+ .hasIndex = 11,
+ .flags = GPBFieldRepeated,
+ .offset = offsetof(ApplyFunctionsTest_Storage, anArray),
+ },
+ };
+ descriptor = [GPBDescriptor
+ allocDescriptorForClass:[self class]
+ rootClass:Nil
+ file:nil
+ fields:fields
+ fieldCount:sizeof(fields) /
+ sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(ApplyFunctionsTest_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+typedef struct {
+ int calledBool;
+ int calledInt32;
+ int calledUInt32;
+ int calledInt64;
+ int calledUInt64;
+ int calledFloat;
+ int calledDouble;
+ int calledObject;
+ int hitCount;
+} TestApplyFunctionsContext;
+
+// Really, who needs templates?
+// Macro for testing apply functions. Declares a variety of different functions
+// base on |NAME|.
+#define TEST_APPLY_FUNCTIONS_FUNC(NAME) \
+ static BOOL TestApplyFunction##NAME(GPBFieldDescriptor *field, \
+ void *voidContext) { \
+ TestApplyFunctionsContext *context = voidContext; \
+ if (field->getSel_ == sel_getUid("stopper")) return NO; \
+ context->called##NAME += 1; \
+ context->hitCount += 1; \
+ return YES; \
+ }
+
+TEST_APPLY_FUNCTIONS_FUNC(Bool)
+TEST_APPLY_FUNCTIONS_FUNC(Int32)
+TEST_APPLY_FUNCTIONS_FUNC(UInt32)
+TEST_APPLY_FUNCTIONS_FUNC(Int64)
+TEST_APPLY_FUNCTIONS_FUNC(UInt64)
+TEST_APPLY_FUNCTIONS_FUNC(Float)
+TEST_APPLY_FUNCTIONS_FUNC(Double)
+TEST_APPLY_FUNCTIONS_FUNC(Object)
+
+@implementation UtilitiesTests
+
+- (void)testRightShiftFunctions {
+ XCTAssertEqual((1UL << 31) >> 31, 1UL);
+ XCTAssertEqual((1 << 31) >> 31, -1);
+ XCTAssertEqual((1ULL << 63) >> 63, 1ULL);
+ XCTAssertEqual((1LL << 63) >> 63, -1LL);
+
+ XCTAssertEqual(GPBLogicalRightShift32((1 << 31), 31), 1);
+ XCTAssertEqual(GPBLogicalRightShift64((1LL << 63), 63), 1LL);
+}
+
+- (void)testMutability {
+ ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message];
+ XCTAssertEqual(0, [foo_message aInt32]);
+ [foo_message setAInt32:100];
+ XCTAssertEqual(100, [foo_message aInt32]);
+}
+
+- (void)testSerializedSize {
+ ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message];
+ [foo_message setAInt32:100];
+ size_t size1 = [foo_message serializedSize];
+ [foo_message setAInt64:100];
+ size_t size2 = [foo_message serializedSize];
+
+ // Intentionally doing a pointer comparison.
+ XCTAssertNotEqual(size1, size2);
+}
+
+- (void)testCopying {
+ ApplyFunctionsTest *foo_message = [ApplyFunctionsTest message];
+ [foo_message setAInt32:100];
+ [foo_message setAObject:@"Happy"];
+ ApplyFunctionsTest *foo = [[foo_message copy] autorelease];
+ XCTAssertNotEqual(foo, foo_message); // Pointer comparision
+ XCTAssertEqualObjects(foo, foo_message);
+}
+
+- (void)testApplyFunctions {
+ // Covers ApplyFunctionsToProtoVariables and
+ // ApplyFunctionsBasedOnEncodingType.
+ // This test depends on the layout of the ivars to be in the order
+ // declared in the interface. If this is not true, it will fail and will
+ // need to be rewritten to accomodate.
+ TestApplyFunctionsContext context;
+ memset(&context, 0, sizeof(context));
+ GPBApplyFunctions foo = GPBAPPLY_FUNCTIONS_INIT(TestApplyFunction);
+ ApplyFunctionsTest *msg = [ApplyFunctionsTest message];
+ GPBApplyFunctionsToMessageFields(&foo, msg, &context);
+
+ // Only eight vars should be set.
+ // "stopper" should cause the loop to quit so it and shouldNotBeCounted should
+ // not be counted.
+ // "_hasTest" should be skipped over.
+ // Each of the vars should only be set once.
+ XCTAssertEqual(context.hitCount, 8);
+ XCTAssertEqual(context.calledBool, 1);
+ XCTAssertEqual(context.calledInt32, 1);
+ XCTAssertEqual(context.calledUInt32, 1);
+ XCTAssertEqual(context.calledInt64, 1);
+ XCTAssertEqual(context.calledUInt64, 1);
+ XCTAssertEqual(context.calledFloat, 1);
+ XCTAssertEqual(context.calledDouble, 1);
+ XCTAssertEqual(context.calledObject, 1);
+}
+
+- (void)testGPBDecodeTextFormatName {
+ uint8_t decodeData[] = {
+ 0x6,
+ // An inlined string (first to make sure the leading null is handled
+ // correctly, and with a key of zero to check that).
+ 0x0, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
+ // All as is (00 op)
+ 0x1, 0x0A, 0x0,
+ // Underscore, upper + 9 (10 op)
+ 0x3, 0xCA, 0x0,
+ // Upper + 3 (10 op), underscore, upper + 5 (10 op)
+ 0x2, 0x44, 0xC6, 0x0,
+ // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op),
+ // underscore, lower + 0 (01 op)
+ 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0,
+ // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op),
+ // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op),
+ // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00 op),
+ // underscore, as is + 3 (00 op)
+ 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
+ };
+ NSString *inputStr = @"abcdefghIJ";
+
+ // Empty inputs
+
+ XCTAssertNil(GPBDecodeTextFormatName(nil, 1, NULL));
+ XCTAssertNil(GPBDecodeTextFormatName(decodeData, 1, NULL));
+ XCTAssertNil(GPBDecodeTextFormatName(nil, 1, inputStr));
+
+ // Keys not found.
+
+ XCTAssertNil(GPBDecodeTextFormatName(decodeData, 5, inputStr));
+ XCTAssertNil(GPBDecodeTextFormatName(decodeData, -1, inputStr));
+
+ // Some name decodes.
+
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1, inputStr), @"abcdefghIJ");
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 2, inputStr), @"Abcd_EfghIJ");
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 3, inputStr), @"_AbcdefghIJ");
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 4, inputStr), @"ABCD__EfghI_j");
+
+ // An inlined string (and key of zero).
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 0, inputStr), @"zbcdefghIJ");
+
+ // Long name so multiple decode ops are needed.
+ inputStr = @"longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
+ XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1000, inputStr),
+ @"long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
+}
+
+- (void)testTextFormat {
+ TestAllTypes *message = [TestAllTypes message];
+
+ // Not kGPBDefaultRepeatCount because we are comparing to golden master file
+ // which was generated with 2.
+ [self setAllFields:message repeatedCount:2];
+
+ NSString *result = GPBTextFormatForMessage(message, nil);
+
+ NSString *fileName = @"text_format_unittest_data.txt";
+ NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
+ NSData *expectedData =
+ [self getDataFileNamed:fileName dataToWrite:resultData];
+ NSString *expected = [[NSString alloc] initWithData:expectedData
+ encoding:NSUTF8StringEncoding];
+ XCTAssertEqualObjects(expected, result);
+ [expected release];
+}
+
+- (void)testTextFormatExtra {
+ // -testTextFormat uses all protos with fields that don't require special
+ // handing for figuring out the names. The ObjC proto has a bunch of oddball
+ // field and enum names that require the decode info to get right, so this
+ // confirms they generated and decoded correctly.
+
+ self_Class *message = [self_Class message];
+ message.cmd = YES;
+ message.isProxy_p = YES;
+ message.subEnum = self_autorelease_RetainCount;
+ message.new_p.copy_p = @"foo";
+
+ NSString *expected = @"_cmd: true\n"
+ @"isProxy: true\n"
+ @"SubEnum: retainCount\n"
+ @"New {\n"
+ @" copy: \"foo\"\n"
+ @"}\n";
+ NSString *result = GPBTextFormatForMessage(message, nil);
+ XCTAssertEqualObjects(expected, result);
+}
+
+- (void)testTextFormatMaps {
+ TestMap *message = [TestMap message];
+
+ // Map iteration order doesn't have to be stable, so use only one entry.
+ [self setAllMapFields:message numEntries:1];
+
+ NSString *result = GPBTextFormatForMessage(message, nil);
+
+ NSString *fileName = @"text_format_map_unittest_data.txt";
+ NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
+ NSData *expectedData =
+ [self getDataFileNamed:fileName dataToWrite:resultData];
+ NSString *expected = [[NSString alloc] initWithData:expectedData
+ encoding:NSUTF8StringEncoding];
+ XCTAssertEqualObjects(expected, result);
+ [expected release];
+}
+
+// TODO(thomasvl): add test with extensions once those format with correct names.
+
+@end
diff --git a/objectivec/Tests/GPBWellKnownTypesTest.m b/objectivec/Tests/GPBWellKnownTypesTest.m
new file mode 100644
index 00000000..78f4e637
--- /dev/null
+++ b/objectivec/Tests/GPBWellKnownTypesTest.m
@@ -0,0 +1,102 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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 "GPBWellKnownTypes.h"
+
+#import <XCTest/XCTest.h>
+
+// A basically random interval into the future for testing with.
+static const NSTimeInterval kFutureOffsetInterval = 15000;
+
+// Nanosecond time accuracy
+static const NSTimeInterval kTimeAccuracy = 1e-9;
+
+@interface WellKnownTypesTest : XCTestCase
+@end
+
+@implementation WellKnownTypesTest
+
+- (void)testTimeStamp {
+ // Test Creation.
+ NSDate *date = [NSDate date];
+ GPBTimestamp *timeStamp = [[GPBTimestamp alloc] initWithDate:date];
+ NSDate *timeStampDate = timeStamp.date;
+
+ // Comparing timeIntervals instead of directly comparing dates because date
+ // equality requires the time intervals to be exactly the same, and the
+ // timeintervals go through a bit of floating point error as they are
+ // converted back and forth from the internal representation.
+ XCTAssertEqualWithAccuracy(date.timeIntervalSince1970,
+ timeStampDate.timeIntervalSince1970,
+ kTimeAccuracy);
+
+ NSTimeInterval time = [date timeIntervalSince1970];
+ GPBTimestamp *timeStamp2 =
+ [[GPBTimestamp alloc] initWithTimeIntervalSince1970:time];
+ NSTimeInterval durationTime = timeStamp2.timeIntervalSince1970;
+ XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+ [timeStamp release];
+
+ // Test Mutation.
+ date = [NSDate dateWithTimeIntervalSinceNow:kFutureOffsetInterval];
+ timeStamp2.date = date;
+ timeStampDate = timeStamp2.date;
+ XCTAssertEqualWithAccuracy(date.timeIntervalSince1970,
+ timeStampDate.timeIntervalSince1970,
+ kTimeAccuracy);
+
+ time = date.timeIntervalSince1970;
+ timeStamp2.timeIntervalSince1970 = time;
+ durationTime = timeStamp2.timeIntervalSince1970;
+ XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+ [timeStamp2 release];
+}
+
+- (void)testDuration {
+ // Test Creation.
+ NSTimeInterval time = [[NSDate date] timeIntervalSince1970];
+ GPBDuration *duration =
+ [[GPBDuration alloc] initWithTimeIntervalSince1970:time];
+ NSTimeInterval durationTime = duration.timeIntervalSince1970;
+ XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+ [duration release];
+
+ // Test Mutation.
+ GPBDuration *duration2 =
+ [[GPBDuration alloc] initWithTimeIntervalSince1970:time];
+ NSDate *date = [NSDate dateWithTimeIntervalSinceNow:kFutureOffsetInterval];
+ time = date.timeIntervalSince1970;
+ duration2.timeIntervalSince1970 = time;
+ durationTime = duration2.timeIntervalSince1970;
+ XCTAssertEqualWithAccuracy(time, durationTime, kTimeAccuracy);
+ [duration2 release];
+}
+
+@end
diff --git a/objectivec/Tests/GPBWireFormatTests.m b/objectivec/Tests/GPBWireFormatTests.m
new file mode 100644
index 00000000..1344af08
--- /dev/null
+++ b/objectivec/Tests/GPBWireFormatTests.m
@@ -0,0 +1,246 @@
+// 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 "GPBTestUtilities.h"
+
+#import "GPBCodedInputStream.h"
+#import "GPBMessage_PackagePrivate.h"
+#import "GPBField_PackagePrivate.h"
+#import "google/protobuf/Unittest.pbobjc.h"
+#import "google/protobuf/UnittestMset.pbobjc.h"
+
+@interface WireFormatTests : GPBTestCase
+@end
+
+@implementation WireFormatTests
+
+- (void)testSerialization {
+ TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+
+ NSData* rawBytes = message.data;
+ XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+ TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes];
+
+ [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSerializationPacked {
+ TestPackedTypes* message =
+ [self packedSetRepeatedCount:kGPBDefaultRepeatCount];
+
+ NSData* rawBytes = message.data;
+ XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+ TestPackedTypes* message2 = [TestPackedTypes parseFromData:rawBytes];
+
+ [self assertPackedFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSerializeExtensions {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serealize a TestAllExtensions then parse it as TestAllTypes
+ // it should work.
+
+ TestAllExtensions* message =
+ [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes = message.data;
+ XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
+
+ TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes];
+
+ [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+- (void)testSerializePackedExtensions {
+ // TestPackedTypes and TestPackedExtensions should have compatible wire
+ // formats; check that they serialize to the same string.
+ TestPackedExtensions* message =
+ [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes = message.data;
+
+ TestPackedTypes* message2 =
+ [self packedSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes2 = message2.data;
+
+ XCTAssertEqualObjects(rawBytes, rawBytes2);
+}
+
+- (void)testParseExtensions {
+ // TestAllTypes and TestAllExtensions should have compatible wire formats,
+ // so if we serialize a TestAllTypes then parse it as TestAllExtensions
+ // it should work.
+
+ TestAllTypes* message = [self allSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes = message.data;
+
+ GPBExtensionRegistry* registry = [self extensionRegistry];
+
+ TestAllExtensions* message2 =
+ [TestAllExtensions parseFromData:rawBytes extensionRegistry:registry];
+
+ [self assertAllExtensionsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
+}
+
+
+- (void) testExtensionsSerializedSize {
+ size_t allSet = [self allSetRepeatedCount:kGPBDefaultRepeatCount].serializedSize;
+ size_t extensionSet = [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount].serializedSize;
+ XCTAssertEqual(allSet, extensionSet);
+}
+
+- (void)testParsePackedExtensions {
+ // Ensure that packed extensions can be properly parsed.
+ TestPackedExtensions* message =
+ [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+ NSData* rawBytes = message.data;
+
+ GPBExtensionRegistry* registry = [self extensionRegistry];
+
+ TestPackedExtensions* message2 =
+ [TestPackedExtensions parseFromData:rawBytes extensionRegistry:registry];
+
+ [self assertPackedExtensionsSet:message2
+ repeatedCount:kGPBDefaultRepeatCount];
+}
+
+const int kUnknownTypeId = 1550055;
+
+- (void)testSerializeMessageSet {
+ // Set up a TestMessageSet with two known messages and an unknown one.
+ TestMessageSet* message_set = [TestMessageSet message];
+ [[message_set getExtension:[TestMessageSetExtension1 messageSetExtension]]
+ setI:123];
+ [[message_set getExtension:[TestMessageSetExtension2 messageSetExtension]]
+ setStr:@"foo"];
+ GPBField* unknownField =
+ [[[GPBField alloc] initWithNumber:kUnknownTypeId] autorelease];
+ [unknownField addLengthDelimited:[NSData dataWithBytes:"bar" length:3]];
+ GPBUnknownFieldSet* unknownFieldSet =
+ [[[GPBUnknownFieldSet alloc] init] autorelease];
+ [unknownFieldSet addField:unknownField];
+ [message_set setUnknownFields:unknownFieldSet];
+
+ NSData* data = [message_set data];
+
+ // Parse back using RawMessageSet and check the contents.
+ RawMessageSet* raw = [RawMessageSet parseFromData:data];
+
+ XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0);
+
+ XCTAssertEqual(raw.itemArray.count, (NSUInteger)3);
+ XCTAssertEqual([raw.itemArray[0] typeId],
+ [TestMessageSetExtension1 messageSetExtension].fieldNumber);
+ XCTAssertEqual([raw.itemArray[1] typeId],
+ [TestMessageSetExtension2 messageSetExtension].fieldNumber);
+ XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId);
+
+ TestMessageSetExtension1* message1 =
+ [TestMessageSetExtension1 parseFromData:[raw.itemArray[0] message]];
+ XCTAssertEqual(message1.i, 123);
+
+ TestMessageSetExtension2* message2 =
+ [TestMessageSetExtension2 parseFromData:[raw.itemArray[1] message]];
+ XCTAssertEqualObjects(message2.str, @"foo");
+
+ XCTAssertEqualObjects([raw.itemArray[2] message],
+ [NSData dataWithBytes:"bar" length:3]);
+}
+
+- (void)testParseMessageSet {
+ // Set up a RawMessageSet with two known messages and an unknown one.
+ RawMessageSet* raw = [RawMessageSet message];
+
+ {
+ RawMessageSet_Item* item = [RawMessageSet_Item message];
+ item.typeId = [TestMessageSetExtension1 messageSetExtension].fieldNumber;
+ TestMessageSetExtension1* message = [TestMessageSetExtension1 message];
+ message.i = 123;
+ item.message = [message data];
+ raw.itemArray = [NSMutableArray array];
+ [raw.itemArray addObject:item];
+ }
+
+ {
+ RawMessageSet_Item* item = [RawMessageSet_Item message];
+ item.typeId = [TestMessageSetExtension2 messageSetExtension].fieldNumber;
+ TestMessageSetExtension2* message = [TestMessageSetExtension2 message];
+ message.str = @"foo";
+ item.message = [message data];
+ [raw.itemArray addObject:item];
+ }
+
+ {
+ RawMessageSet_Item* item = [RawMessageSet_Item message];
+ item.typeId = kUnknownTypeId;
+ item.message = [NSData dataWithBytes:"bar" length:3];
+ [raw.itemArray addObject:item];
+ }
+
+ NSData* data = [raw data];
+
+ // Parse as a TestMessageSet and check the contents.
+ TestMessageSet* messageSet =
+ [TestMessageSet parseFromData:data
+ extensionRegistry:[UnittestMsetRoot extensionRegistry]];
+
+ XCTAssertEqual(
+ [[messageSet
+ getExtension:[TestMessageSetExtension1 messageSetExtension]] i],
+ 123);
+ XCTAssertEqualObjects(
+ [[messageSet
+ getExtension:[TestMessageSetExtension2 messageSetExtension]] str],
+ @"foo");
+
+ XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1);
+ GPBField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId];
+ XCTAssertNotNil(unknownField);
+ XCTAssertEqual(unknownField.lengthDelimitedList.count, (NSUInteger)1);
+ XCTAssertEqualObjects(unknownField.lengthDelimitedList[0],
+ [NSData dataWithBytes:"bar" length:3]);
+}
+
+- (void)assertFieldsInOrder:(NSData*)data {
+ GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
+ int32_t previousTag = 0;
+
+ while (YES) {
+ int32_t tag = [input readTag];
+ if (tag == 0) {
+ break;
+ }
+
+ XCTAssertGreaterThan(tag, previousTag);
+ [input skipField:tag];
+ }
+}
+
+@end
diff --git a/objectivec/Tests/UnitTests-Bridging-Header.h b/objectivec/Tests/UnitTests-Bridging-Header.h
new file mode 100644
index 00000000..46292fce
--- /dev/null
+++ b/objectivec/Tests/UnitTests-Bridging-Header.h
@@ -0,0 +1,6 @@
+//
+// Use this file to import your target's public headers that you would like to expose to Swift.
+//
+
+#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
diff --git a/objectivec/Tests/UnitTests-Info.plist b/objectivec/Tests/UnitTests-Info.plist
new file mode 100644
index 00000000..65013556
--- /dev/null
+++ b/objectivec/Tests/UnitTests-Info.plist
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>English</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.yourcompany.${PRODUCT_NAME:identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundlePackageType</key>
+ <string>BNDL</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+</dict>
+</plist>
diff --git a/objectivec/Tests/golden_message b/objectivec/Tests/golden_message
new file mode 100644
index 00000000..7bceab41
--- /dev/null
+++ b/objectivec/Tests/golden_message
Binary files differ
diff --git a/objectivec/Tests/golden_packed_fields_message b/objectivec/Tests/golden_packed_fields_message
new file mode 100644
index 00000000..7bceab41
--- /dev/null
+++ b/objectivec/Tests/golden_packed_fields_message
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/AppDelegate.m b/objectivec/Tests/iOSTestHarness/AppDelegate.m
new file mode 100644
index 00000000..8c4a586b
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/AppDelegate.m
@@ -0,0 +1,35 @@
+#import <UIKit/UIKit.h>
+
+@interface AppDelegate : UIResponder <UIApplicationDelegate>
+@property (strong, nonatomic) UIWindow *window;
+@end
+
+@implementation AppDelegate
+
+@synthesize window;
+
+- (BOOL)application:(UIApplication *)application
+ didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
+ #pragma unused (application, launchOptions)
+
+ self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
+ self.window.backgroundColor = [UIColor whiteColor];
+ [self.window makeKeyAndVisible];
+ self.window.rootViewController = [[UIViewController alloc] init];
+
+ UILabel *label =
+ [[UILabel alloc] initWithFrame:CGRectMake(0, 200, CGRectGetWidth(self.window.frame), 40)];
+ label.text = @"Protocol Buffer Test Harness";
+ label.textAlignment = NSTextAlignmentCenter;
+ [self.window addSubview:label];
+
+ return YES;
+}
+
+@end
+
+int main(int argc, char * argv[]) {
+ @autoreleasepool {
+ return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
+ }
+}
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json
new file mode 100644
index 00000000..ecd3584e
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/Contents.json
@@ -0,0 +1,116 @@
+{
+ "images" : [
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "29x29",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "iphone",
+ "size" : "40x40",
+ "scale" : "3x"
+ },
+ {
+ "size" : "57x57",
+ "idiom" : "iphone",
+ "filename" : "iPhone6.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "57x57",
+ "idiom" : "iphone",
+ "filename" : "iPhone6@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "iPhone7@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "60x60",
+ "idiom" : "iphone",
+ "filename" : "iPhone7@3x.png",
+ "scale" : "3x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "29x29",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "40x40",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "50x50",
+ "scale" : "1x"
+ },
+ {
+ "idiom" : "ipad",
+ "size" : "50x50",
+ "scale" : "2x"
+ },
+ {
+ "size" : "72x72",
+ "idiom" : "ipad",
+ "filename" : "iPad6.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "72x72",
+ "idiom" : "ipad",
+ "filename" : "iPad6@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "iPad7.png",
+ "scale" : "1x"
+ },
+ {
+ "size" : "76x76",
+ "idiom" : "ipad",
+ "filename" : "iPad7@2x.png",
+ "scale" : "2x"
+ },
+ {
+ "idiom" : "car",
+ "size" : "120x120",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png
new file mode 100644
index 00000000..43da2ee4
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png
new file mode 100644
index 00000000..2ec93704
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad6@2x.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png
new file mode 100644
index 00000000..aec8bc1b
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png
new file mode 100644
index 00000000..e39cc3e7
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPad7@2x.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png
new file mode 100644
index 00000000..5572d79f
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png
new file mode 100644
index 00000000..2424997f
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone6@2x.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png
new file mode 100644
index 00000000..10bfc3cf
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@2x.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png
new file mode 100644
index 00000000..8d16f14d
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/AppIcon.appiconset/iPhone7@3x.png
Binary files differ
diff --git a/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json b/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json
new file mode 100644
index 00000000..5a296668
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Images.xcassets/LaunchImage.launchimage/Contents.json
@@ -0,0 +1,49 @@
+{
+ "images" : [
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "minimum-system-version" : "7.0",
+ "extent" : "full-screen",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "minimum-system-version" : "7.0",
+ "extent" : "full-screen",
+ "scale" : "1x"
+ },
+ {
+ "orientation" : "landscape",
+ "idiom" : "ipad",
+ "minimum-system-version" : "7.0",
+ "extent" : "full-screen",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "minimum-system-version" : "7.0",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "iphone",
+ "minimum-system-version" : "7.0",
+ "subtype" : "retina4",
+ "scale" : "2x"
+ },
+ {
+ "orientation" : "portrait",
+ "idiom" : "ipad",
+ "minimum-system-version" : "7.0",
+ "extent" : "full-screen",
+ "scale" : "1x"
+ }
+ ],
+ "info" : {
+ "version" : 1,
+ "author" : "xcode"
+ }
+} \ No newline at end of file
diff --git a/objectivec/Tests/iOSTestHarness/Info.plist b/objectivec/Tests/iOSTestHarness/Info.plist
new file mode 100644
index 00000000..31ab1578
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/Info.plist
@@ -0,0 +1,43 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
+<plist version="1.0">
+<dict>
+ <key>CFBundleDevelopmentRegion</key>
+ <string>en</string>
+ <key>CFBundleDisplayName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundleExecutable</key>
+ <string>${EXECUTABLE_NAME}</string>
+ <key>CFBundleIdentifier</key>
+ <string>com.google.${PRODUCT_NAME:rfc1034identifier}</string>
+ <key>CFBundleInfoDictionaryVersion</key>
+ <string>6.0</string>
+ <key>CFBundleName</key>
+ <string>${PRODUCT_NAME}</string>
+ <key>CFBundlePackageType</key>
+ <string>APPL</string>
+ <key>CFBundleShortVersionString</key>
+ <string>1.0</string>
+ <key>CFBundleSignature</key>
+ <string>????</string>
+ <key>CFBundleVersion</key>
+ <string>1.0</string>
+ <key>LSRequiresIPhoneOS</key>
+ <true/>
+ <key>UILaunchStoryboardName</key>
+ <string>LaunchScreen</string>
+ <key>UISupportedInterfaceOrientations</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ </array>
+ <key>UISupportedInterfaceOrientations~ipad</key>
+ <array>
+ <string>UIInterfaceOrientationPortrait</string>
+ <string>UIInterfaceOrientationLandscapeLeft</string>
+ <string>UIInterfaceOrientationLandscapeRight</string>
+ <string>UIInterfaceOrientationPortraitUpsideDown</string>
+ </array>
+</dict>
+</plist>
diff --git a/objectivec/Tests/iOSTestHarness/LaunchScreen.xib b/objectivec/Tests/iOSTestHarness/LaunchScreen.xib
new file mode 100644
index 00000000..22204bfe
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/LaunchScreen.xib
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="6254" systemVersion="13F34" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" launchScreen="YES" useTraitCollections="YES">
+ <dependencies>
+ <deployment identifier="iOS"/>
+ <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="6247"/>
+ <capability name="Constraints with non-1.0 multipliers" minToolsVersion="5.1"/>
+ </dependencies>
+ <objects>
+ <placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner"/>
+ <placeholder placeholderIdentifier="IBFirstResponder" id="-2" customClass="UIResponder"/>
+ <view contentMode="scaleToFill" id="iN0-l3-epB">
+ <rect key="frame" x="0.0" y="0.0" width="630" height="503"/>
+ <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
+ <subviews>
+ <label opaque="NO" clipsSubviews="YES" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Protocol Buffer Test Harness" textAlignment="center" lineBreakMode="middleTruncation" baselineAdjustment="alignBaselines" minimumFontSize="18" translatesAutoresizingMaskIntoConstraints="NO" id="kId-c2-rCX">
+ <rect key="frame" x="20" y="147" width="591" height="43"/>
+ <fontDescription key="fontDescription" type="boldSystem" pointSize="36"/>
+ <color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
+ <nil key="highlightedColor"/>
+ </label>
+ </subviews>
+ <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
+ <constraints>
+ <constraint firstItem="kId-c2-rCX" firstAttribute="centerY" secondItem="iN0-l3-epB" secondAttribute="bottom" multiplier="1/3" constant="1" id="Kid-kn-2rF"/>
+ <constraint firstAttribute="centerX" secondItem="kId-c2-rCX" secondAttribute="centerX" id="Koa-jz-hwk"/>
+ <constraint firstItem="kId-c2-rCX" firstAttribute="leading" secondItem="iN0-l3-epB" secondAttribute="leading" constant="20" symbolic="YES" id="fvb-Df-36g"/>
+ </constraints>
+ <nil key="simulatedStatusBarMetrics"/>
+ <freeformSimulatedSizeMetrics key="simulatedDestinationMetrics"/>
+ <point key="canvasLocation" x="479" y="456.5"/>
+ </view>
+ </objects>
+</document>
diff --git a/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings b/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings
new file mode 100644
index 00000000..477b28ff
--- /dev/null
+++ b/objectivec/Tests/iOSTestHarness/en.lproj/InfoPlist.strings
@@ -0,0 +1,2 @@
+/* Localized versions of Info.plist keys */
+
diff --git a/objectivec/Tests/text_format_map_unittest_data.txt b/objectivec/Tests/text_format_map_unittest_data.txt
new file mode 100644
index 00000000..ad1195e2
--- /dev/null
+++ b/objectivec/Tests/text_format_map_unittest_data.txt
@@ -0,0 +1,70 @@
+map_int32_int32 {
+ key: 100
+ value: 1
+}
+map_int64_int64 {
+ key: 101
+ value: 1
+}
+map_uint32_uint32 {
+ key: 102
+ value: 1
+}
+map_uint64_uint64 {
+ key: 103
+ value: 1
+}
+map_sint32_sint32 {
+ key: 104
+ value: 1
+}
+map_sint64_sint64 {
+ key: 105
+ value: 1
+}
+map_fixed32_fixed32 {
+ key: 106
+ value: 1
+}
+map_fixed64_fixed64 {
+ key: 107
+ value: 1
+}
+map_sfixed32_sfixed32 {
+ key: 108
+ value: 1
+}
+map_sfixed64_sfixed64 {
+ key: 109
+ value: 1
+}
+map_int32_float {
+ key: 110
+ value: 1
+}
+map_int32_double {
+ key: 111
+ value: 1
+}
+map_bool_bool {
+ key: true
+ value: false
+}
+map_string_string {
+ key: "112"
+ value: "1"
+}
+map_int32_bytes {
+ key: 113
+ value: "\001\000\000\000"
+}
+map_int32_enum {
+ key: 114
+ value: MAP_ENUM_BAZ
+}
+map_int32_foreign_message {
+ key: 115
+ value {
+ c: 1
+ }
+}
diff --git a/objectivec/Tests/text_format_unittest_data.txt b/objectivec/Tests/text_format_unittest_data.txt
new file mode 100644
index 00000000..d10f1000
--- /dev/null
+++ b/objectivec/Tests/text_format_unittest_data.txt
@@ -0,0 +1,116 @@
+optional_int32: 101
+optional_int64: 102
+optional_uint32: 103
+optional_uint64: 104
+optional_sint32: 105
+optional_sint64: 106
+optional_fixed32: 107
+optional_fixed64: 108
+optional_sfixed32: 109
+optional_sfixed64: 110
+optional_float: 111
+optional_double: 112
+optional_bool: true
+optional_string: "115"
+optional_bytes: "\001\000\002\003\000\005"
+OptionalGroup {
+ a: 117
+}
+optional_nested_message {
+ bb: 118
+}
+optional_foreign_message {
+ c: 119
+}
+optional_import_message {
+ d: 120
+}
+optional_nested_enum: BAZ
+optional_foreign_enum: FOREIGN_BAZ
+optional_import_enum: IMPORT_BAZ
+optional_string_piece: "124"
+optional_cord: "125"
+repeated_int32: 201
+repeated_int32: 301
+repeated_int64: 202
+repeated_int64: 302
+repeated_uint32: 203
+repeated_uint32: 303
+repeated_uint64: 204
+repeated_uint64: 304
+repeated_sint32: 205
+repeated_sint32: 305
+repeated_sint64: 206
+repeated_sint64: 306
+repeated_fixed32: 207
+repeated_fixed32: 307
+repeated_fixed64: 208
+repeated_fixed64: 308
+repeated_sfixed32: 209
+repeated_sfixed32: 309
+repeated_sfixed64: 210
+repeated_sfixed64: 310
+repeated_float: 211
+repeated_float: 311
+repeated_double: 212
+repeated_double: 312
+repeated_bool: false
+repeated_bool: true
+repeated_string: "215"
+repeated_string: "315"
+repeated_bytes: "\330\000\000\000"
+repeated_bytes: "<\001\000\000"
+RepeatedGroup {
+ a: 217
+}
+RepeatedGroup {
+ a: 317
+}
+repeated_nested_message {
+ bb: 218
+}
+repeated_nested_message {
+ bb: 318
+}
+repeated_foreign_message {
+ c: 219
+}
+repeated_foreign_message {
+ c: 319
+}
+repeated_import_message {
+ d: 220
+}
+repeated_import_message {
+ d: 320
+}
+repeated_nested_enum: BAZ
+repeated_nested_enum: BAR
+repeated_foreign_enum: FOREIGN_BAZ
+repeated_foreign_enum: FOREIGN_BAR
+repeated_import_enum: IMPORT_BAZ
+repeated_import_enum: IMPORT_BAR
+repeated_string_piece: "224"
+repeated_string_piece: "324"
+repeated_cord: "225"
+repeated_cord: "325"
+default_int32: 401
+default_int64: 402
+default_uint32: 403
+default_uint64: 404
+default_sint32: 405
+default_sint64: 406
+default_fixed32: 407
+default_fixed64: 408
+default_sfixed32: 409
+default_sfixed64: 410
+default_float: 411
+default_double: 412
+default_bool: false
+default_string: "415"
+default_bytes: "\240\001\000\000"
+default_nested_enum: FOO
+default_foreign_enum: FOREIGN_FOO
+default_import_enum: IMPORT_FOO
+default_string_piece: "424"
+default_cord: "425"
diff --git a/objectivec/Tests/unittest_cycle.proto b/objectivec/Tests/unittest_cycle.proto
new file mode 100644
index 00000000..5f6f56a1
--- /dev/null
+++ b/objectivec/Tests/unittest_cycle.proto
@@ -0,0 +1,58 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+// Cycles in the Message graph can cause problems for the mutable classes
+// since the properties on the mutable class change types. This file just
+// needs to generate source, and that source must compile, to ensure the
+// generated source works for this sort of case.
+
+// You can't make a object graph that spans files, so this can only be done
+// within a single proto file.
+
+message CycleFoo {
+ optional CycleFoo a_foo = 1;
+ optional CycleBar a_bar = 2;
+ optional CycleBaz a_baz = 3;
+}
+
+message CycleBar {
+ optional CycleBar a_bar = 1;
+ optional CycleBaz a_baz = 2;
+ optional CycleFoo a_foo = 3;
+}
+
+message CycleBaz {
+ optional CycleBaz a_baz = 1;
+ optional CycleFoo a_foo = 2;
+ optional CycleBar a_bar = 3;
+}
diff --git a/objectivec/Tests/unittest_filter.proto b/objectivec/Tests/unittest_filter.proto
new file mode 100644
index 00000000..1398dfc8
--- /dev/null
+++ b/objectivec/Tests/unittest_filter.proto
@@ -0,0 +1,71 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2013 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+
+message Keep {
+}
+
+message Remove {
+}
+
+message RemoveJustKidding {
+}
+
+message Other {
+ optional Keep a = 1;
+ optional Remove b = 2;
+}
+
+enum RemoveEnum {
+ RemoveValue = 1;
+}
+
+enum KeepEnum {
+ KeepValue = 1;
+}
+
+message RemoveEnumMessage {
+ enum KeepEnumInside {
+ KeepValue = 1;
+ }
+
+ enum RemoveEnumInside {
+ RemoveValue = 1;
+ }
+
+ message KeepNestedInside {
+ }
+
+ message RemoveNestedInside {
+ }
+}
diff --git a/objectivec/Tests/unittest_name_mangling.proto b/objectivec/Tests/unittest_name_mangling.proto
new file mode 100644
index 00000000..aadad6d6
--- /dev/null
+++ b/objectivec/Tests/unittest_name_mangling.proto
@@ -0,0 +1,37 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+option objc_class_prefix = "ABC";
+
+package protobuf_unittest;
+
+// TODO(thomasvl): Add tests for the special cases in name mangling.
+
diff --git a/objectivec/Tests/unittest_objc.proto b/objectivec/Tests/unittest_objc.proto
new file mode 100644
index 00000000..d288a30d
--- /dev/null
+++ b/objectivec/Tests/unittest_objc.proto
@@ -0,0 +1,389 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2011 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+import "google/protobuf/unittest.proto";
+
+package protobuf_unittest;
+
+// Using the messages in unittest.proto, setup for recursive cases for testing
+// extensions at various depths.
+extend TestAllExtensions {
+ optional TestAllExtensions recursive_extension = 86;
+}
+
+// Recursive message to for testing autocreators at different depths.
+message TestRecursiveMessageWithRepeatedField {
+ optional TestRecursiveMessageWithRepeatedField a = 1;
+ repeated int32 i = 2;
+ repeated string str = 3;
+}
+
+// Recursive message and extension to for testing autocreators at different
+// depths.
+message TestRecursiveExtension {
+ optional TestRecursiveExtension recursive_sub_message = 1;
+ repeated int32 repeated_value = 2;
+ extensions 1000 to max;
+}
+
+extend TestRecursiveExtension {
+ optional TestRecursiveExtension recursive_message_extension = 1000;
+}
+
+message self {
+ message super {
+ optional int32 description = 1;
+ }
+
+ enum autorelease {
+ retain = 1;
+ release = 2;
+ retainCount = 3;
+ }
+
+ // Singular
+ optional bool id = 1;
+ optional bool _cmd = 2;
+ optional bool in = 3;
+ optional bool out = 4;
+ optional bool inout = 5;
+ optional bool bycopy = 6;
+ optional bool byref = 7;
+ optional bool oneway = 8;
+ optional bool dealloc = 9;
+ optional bool zone = 10;
+ optional bool isProxy = 11;
+ optional bool copy = 12;
+ optional bool readonly = 13;
+ optional bool default = 14;
+ optional bool assign = 15;
+ optional bool getter = 16;
+ optional bool setter = 17;
+ optional bool weak = 18;
+ optional bool public = 19;
+ optional bool case = 20;
+
+ optional autorelease SubEnum = 25;
+
+ optional group New = 50 {
+ optional string copy = 51;
+ }
+ optional group MutableCopy = 60 {
+ optional int32 extensionRegistry = 61;
+ }
+
+ extensions 90 to 94;
+
+}
+
+enum retain {
+ count = 4;
+ initialized = 5;
+ serializedSize = 6;
+}
+
+// EnumValueShortName: The short names shouldn't get suffixes/prefixes.
+enum Foo {
+ SERIALIZED_SIZE = 1;
+ SIZE = 2;
+ OTHER = 3;
+}
+
+// EnumValueShortName: The enum name gets a prefix.
+enum Category {
+ RED = 1;
+ BLUE = 2;
+}
+
+// EnumValueShortName: Twist case, full name gets PB, but the short names
+// should still end up correct.
+enum Time {
+ BASE = 1;
+ RECORD = 2;
+ SOMETHING_ELSE = 3;
+}
+
+extend self {
+ repeated int32 debugDescription = 90 [packed = true];
+ repeated int64 finalize = 91 [packed = true];
+ repeated uint32 hash = 92 [packed = true];
+ repeated uint64 classForCoder = 93 [packed = true];
+ repeated sint32 byref = 94 [packed = true];
+}
+
+// Test handing of fields that start with init* since Xcode 5's ARC support
+// doesn't like messages that look like initializers but aren't.
+message ObjCInitFoo {
+ optional string init_val = 11;
+ optional int32 init_size = 12;
+ optional self init_self = 13;
+
+ repeated string init_vals = 21;
+ repeated int32 init_sizes = 22;
+ repeated self init_selfs = 23;
+}
+
+// Test handling of fields that start with retained names.
+message ObjCRetainedFoo {
+ optional string new_val_lower_complex = 11;
+ optional string new_Val_upper_complex = 12;
+ optional string newvalue_lower_no_underscore_complex = 13;
+ optional string newValue_upper_no_underscore_complex = 14;
+
+ optional int32 new_val_lower_primitive = 15;
+ optional int32 new_Val_upper_primitive = 16;
+ optional int32 newvalue_lower_no_underscore_primitive = 17;
+ optional int32 newValue_upper_no_underscore_primitive = 18;
+
+ optional self new_val_lower_message = 19;
+ optional self new_Val_upper_message = 20;
+ optional self newvalue_lower_no_underscore_message = 21;
+ optional self newValue_upper_no_underscore_message = 22;
+
+ optional Foo new_val_lower_enum = 23;
+ optional Foo new_Val_upper_enum = 24;
+ optional Foo newvalue_lower_no_underscore_enum = 25;
+ optional Foo newValue_upper_no_underscore_enum = 26;
+
+ repeated string new_val_lower_complex_repeated = 111;
+ repeated string new_Val_upper_complex_repeated = 112;
+ repeated string newvalue_lower_no_underscore_complex_repeated = 113;
+ repeated string newValue_upper_no_underscore_complex_repeated = 114;
+
+ repeated int32 new_val_lower_primitive_repeated = 115;
+ repeated int32 new_Val_upper_primitive_repeated = 116;
+ repeated int32 newvalue_lower_no_underscore_primitive_repeated = 117;
+ repeated int32 newValue_upper_no_underscore_primitive_repeated = 118;
+
+ repeated self new_val_lower_message_repeated = 119;
+ repeated self new_Val_upper_message_repeated = 120;
+ repeated self newvalue_lower_no_underscore_message_repeated = 121;
+ repeated self newValue_upper_no_underscore_message_repeated = 122;
+
+ repeated Foo new_val_lower_enum_repeated = 123;
+ repeated Foo new_Val_upper_enum_repeated = 124;
+ repeated Foo newvalue_lower_no_underscore_enum_repeated = 125;
+ repeated Foo newValue_upper_no_underscore_enum_repeated = 126;
+
+ optional string alloc_val_lower_complex = 211;
+ optional string alloc_Val_upper_complex = 212;
+ optional string allocvalue_lower_no_underscore_complex = 213;
+ optional string allocValue_upper_no_underscore_complex = 214;
+
+ optional int32 alloc_val_lower_primitive = 215;
+ optional int32 alloc_Val_upper_primitive = 216;
+ optional int32 allocvalue_lower_no_underscore_primitive = 217;
+ optional int32 allocValue_upper_no_underscore_primitive = 218;
+
+ optional self alloc_val_lower_message = 219;
+ optional self alloc_Val_upper_message = 220;
+ optional self allocvalue_lower_no_underscore_message = 221;
+ optional self allocValue_upper_no_underscore_message = 222;
+
+ optional Foo alloc_val_lower_enum = 223;
+ optional Foo alloc_Val_upper_enum = 224;
+ optional Foo allocvalue_lower_no_underscore_enum = 225;
+ optional Foo allocValue_upper_no_underscore_enum = 226;
+
+ repeated string alloc_val_lower_complex_repeated = 311;
+ repeated string alloc_Val_upper_complex_repeated = 312;
+ repeated string allocvalue_lower_no_underscore_complex_repeated = 313;
+ repeated string allocValue_upper_no_underscore_complex_repeated = 314;
+
+ repeated int32 alloc_val_lower_primitive_repeated = 315;
+ repeated int32 alloc_Val_upper_primitive_repeated = 316;
+ repeated int32 allocvalue_lower_no_underscore_primitive_repeated = 317;
+ repeated int32 allocValue_upper_no_underscore_primitive_repeated = 318;
+
+ repeated self alloc_val_lower_message_repeated = 319;
+ repeated self alloc_Val_upper_message_repeated = 320;
+ repeated self allocvalue_lower_no_underscore_message_repeated = 321;
+ repeated self allocValue_upper_no_underscore_message_repeated = 322;
+
+ repeated Foo alloc_val_lower_enum_repeated = 323;
+ repeated Foo alloc_Val_upper_enum_repeated = 324;
+ repeated Foo allocvalue_lower_no_underscore_enum_repeated = 325;
+ repeated Foo allocValue_upper_no_underscore_enum_repeated = 326;
+
+ optional string copy_val_lower_complex = 411;
+ optional string copy_Val_upper_complex = 412;
+ optional string copyvalue_lower_no_underscore_complex = 413;
+ optional string copyValue_upper_no_underscore_complex = 414;
+
+ optional int32 copy_val_lower_primitive = 415;
+ optional int32 copy_Val_upper_primitive = 416;
+ optional int32 copyvalue_lower_no_underscore_primitive = 417;
+ optional int32 copyValue_upper_no_underscore_primitive = 418;
+
+ optional self copy_val_lower_message = 419;
+ optional self copy_Val_upper_message = 420;
+ optional self copyvalue_lower_no_underscore_message = 421;
+ optional self copyValue_upper_no_underscore_message = 422;
+
+ optional Foo copy_val_lower_enum = 423;
+ optional Foo copy_Val_upper_enum = 424;
+ optional Foo copyvalue_lower_no_underscore_enum = 425;
+ optional Foo copyValue_upper_no_underscore_enum = 426;
+
+ repeated string copy_val_lower_complex_repeated = 511;
+ repeated string copy_Val_upper_complex_repeated = 512;
+ repeated string copyvalue_lower_no_underscore_complex_repeated = 513;
+ repeated string copyValue_upper_no_underscore_complex_repeated = 514;
+
+ repeated int32 copy_val_lower_primitive_repeated = 515;
+ repeated int32 copy_Val_upper_primitive_repeated = 516;
+ repeated int32 copyvalue_lower_no_underscore_primitive_repeated = 517;
+ repeated int32 copyValue_upper_no_underscore_primitive_repeated = 518;
+
+ repeated self copy_val_lower_message_repeated = 519;
+ repeated self copy_Val_upper_message_repeated = 520;
+ repeated self copyvalue_lower_no_underscore_message_repeated = 521;
+ repeated self copyValue_upper_no_underscore_message_repeated = 522;
+
+ repeated Foo copy_val_lower_enum_repeated = 523;
+ repeated Foo copy_Val_upper_enum_repeated = 524;
+ repeated Foo copyvalue_lower_no_underscore_enum_repeated = 525;
+ repeated Foo copyValue_upper_no_underscore_enum_repeated = 526;
+
+ optional string mutableCopy_val_lower_complex = 611;
+ optional string mutableCopy_Val_upper_complex = 612;
+ optional string mutableCopyvalue_lower_no_underscore_complex = 613;
+ optional string mutableCopyValue_upper_no_underscore_complex = 614;
+
+ optional int32 mutableCopy_val_lower_primitive = 615;
+ optional int32 mutableCopy_Val_upper_primitive = 616;
+ optional int32 mutableCopyvalue_lower_no_underscore_primitive = 617;
+ optional int32 mutableCopyValue_upper_no_underscore_primitive = 618;
+
+ optional self mutableCopy_val_lower_message = 619;
+ optional self mutableCopy_Val_upper_message = 620;
+ optional self mutableCopyvalue_lower_no_underscore_message = 621;
+ optional self mutableCopyValue_upper_no_underscore_message = 622;
+
+ optional Foo mutableCopy_val_lower_enum = 623;
+ optional Foo mutableCopy_Val_upper_enum = 624;
+ optional Foo mutableCopyvalue_lower_no_underscore_enum = 625;
+ optional Foo mutableCopyValue_upper_no_underscore_enum = 626;
+
+ repeated string mutableCopy_val_lower_complex_repeated = 711;
+ repeated string mutableCopy_Val_upper_complex_repeated = 712;
+ repeated string mutableCopyvalue_lower_no_underscore_complex_repeated = 713;
+ repeated string mutableCopyValue_upper_no_underscore_complex_repeated = 714;
+
+ repeated int32 mutableCopy_val_lower_primitive_repeated = 715;
+ repeated int32 mutableCopy_Val_upper_primitive_repeated = 716;
+ repeated int32 mutableCopyvalue_lower_no_underscore_primitive_repeated = 717;
+ repeated int32 mutableCopyValue_upper_no_underscore_primitive_repeated = 718;
+
+ repeated self mutableCopy_val_lower_message_repeated = 719;
+ repeated self mutableCopy_Val_upper_message_repeated = 720;
+ repeated self mutableCopyvalue_lower_no_underscore_message_repeated = 721;
+ repeated self mutableCopyValue_upper_no_underscore_message_repeated = 722;
+
+ repeated Foo mutableCopy_val_lower_enum_repeated = 723;
+ repeated Foo mutableCopy_Val_upper_enum_repeated = 724;
+ repeated Foo mutableCopyvalue_lower_no_underscore_enum_repeated = 725;
+ repeated Foo mutableCopyValue_upper_no_underscore_enum_repeated = 726;
+}
+
+// Test handling of fields that are the retained names.
+message ObjCRetainedComplex {
+ optional string new = 1;
+ optional string alloc = 2;
+ optional string copy = 3;
+ optional string mutableCopy = 4;
+}
+
+message ObjCRetainedComplexRepeated {
+ repeated string new = 1;
+ repeated string alloc = 2;
+ repeated string copy = 3;
+ repeated string mutableCopy = 4;
+}
+
+message ObjCRetainedPrimitive {
+ optional int32 new = 1;
+ optional int32 alloc = 2;
+ optional int32 copy = 3;
+ optional int32 mutableCopy = 4;
+}
+
+message ObjCRetainedPrimitiveRepeated {
+ repeated int32 new = 1;
+ repeated int32 alloc = 2;
+ repeated int32 copy = 3;
+ repeated int32 mutableCopy = 4;
+}
+
+message ObjCRetainedMessage {
+ optional self new = 1;
+ optional self alloc = 2;
+ optional self copy = 3;
+ optional self mutableCopy = 4;
+}
+
+message ObjCRetainedMessageRepeated {
+ repeated self new = 1;
+ repeated self alloc = 2;
+ repeated self copy = 3;
+ repeated self mutableCopy = 4;
+}
+
+// Test Handling some MacTypes
+message Point {
+ message Rect {
+ optional int32 TimeValue = 1;
+ }
+}
+
+// Test some weird defaults that we see in protos.
+message ObjcWeirdDefaults {
+ // Set default values that match the protocol buffer defined defaults to
+ // confirm hasDefault and the default values are set correctly.
+ optional string foo = 1 [default = ""];
+ optional bytes bar = 2 [default = ""];
+}
+
+// Used to confirm negative enum values work as expected.
+message EnumTestMsg {
+ enum MyEnum {
+ ZERO = 0;
+ ONE = 1;
+ TWO = 2;
+ NEG_ONE = -1;
+ NEG_TWO = -2;
+ }
+ optional MyEnum foo = 1;
+ optional MyEnum bar = 2 [default = ONE];
+ optional MyEnum baz = 3 [default = NEG_ONE];
+
+ repeated MyEnum mumble = 4;
+}
diff --git a/objectivec/Tests/unittest_runtime_proto2.proto b/objectivec/Tests/unittest_runtime_proto2.proto
new file mode 100644
index 00000000..f9fd3c35
--- /dev/null
+++ b/objectivec/Tests/unittest_runtime_proto2.proto
@@ -0,0 +1,108 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto2";
+
+package protobuf_unittest;
+
+message Message2 {
+ enum Enum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ EXTRA_2 = 20;
+ }
+
+ optional int32 optional_int32 = 1;
+ optional int64 optional_int64 = 2;
+ optional uint32 optional_uint32 = 3;
+ optional uint64 optional_uint64 = 4;
+ optional sint32 optional_sint32 = 5;
+ optional sint64 optional_sint64 = 6;
+ optional fixed32 optional_fixed32 = 7;
+ optional fixed64 optional_fixed64 = 8;
+ optional sfixed32 optional_sfixed32 = 9;
+ optional sfixed64 optional_sfixed64 = 10;
+ optional float optional_float = 11;
+ optional double optional_double = 12;
+ optional bool optional_bool = 13;
+ optional string optional_string = 14;
+ optional bytes optional_bytes = 15;
+ optional group OptionalGroup = 16 {
+ optional int32 a = 17;
+ }
+ optional Message2 optional_message = 18;
+ optional Enum optional_enum = 19;
+
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+ repeated group RepeatedGroup = 46 {
+ optional int32 a = 47;
+ }
+ repeated Message2 repeated_message = 48;
+ repeated Enum repeated_enum = 49;
+ repeated Enum repeated_packed_enum = 50 [packed=true];
+
+ oneof o {
+ int32 oneof_int32 = 51 [default = 100];
+ int64 oneof_int64 = 52 [default = 101];
+ uint32 oneof_uint32 = 53 [default = 102];
+ uint64 oneof_uint64 = 54 [default = 103];
+ sint32 oneof_sint32 = 55 [default = 104];
+ sint64 oneof_sint64 = 56 [default = 105];
+ fixed32 oneof_fixed32 = 57 [default = 106];
+ fixed64 oneof_fixed64 = 58 [default = 107];
+ sfixed32 oneof_sfixed32 = 59 [default = 108];
+ sfixed64 oneof_sfixed64 = 60 [default = 109];
+ float oneof_float = 61 [default = 110];
+ double oneof_double = 62 [default = 111];
+ bool oneof_bool = 63 [default = true];
+ string oneof_string = 64 [default = "string"];
+ bytes oneof_bytes = 65 [default = "data"];
+ group OneofGroup = 66 {
+ optional int32 a = 67;
+ optional int32 b = 167;
+ }
+ Message2 oneof_message = 68;
+ Enum oneof_enum = 69 [default = BAZ];
+ }
+}
diff --git a/objectivec/Tests/unittest_runtime_proto3.proto b/objectivec/Tests/unittest_runtime_proto3.proto
new file mode 100644
index 00000000..b6a2f4dc
--- /dev/null
+++ b/objectivec/Tests/unittest_runtime_proto3.proto
@@ -0,0 +1,101 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 Google Inc. All rights reserved.
+//
+// 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.
+
+syntax = "proto3";
+
+package protobuf_unittest;
+
+message Message3 {
+ enum Enum {
+ FOO = 0;
+ BAR = 1;
+ BAZ = 2;
+ EXTRA_3 = 30;
+ }
+
+ int32 optional_int32 = 1;
+ int64 optional_int64 = 2;
+ uint32 optional_uint32 = 3;
+ uint64 optional_uint64 = 4;
+ sint32 optional_sint32 = 5;
+ sint64 optional_sint64 = 6;
+ fixed32 optional_fixed32 = 7;
+ fixed64 optional_fixed64 = 8;
+ sfixed32 optional_sfixed32 = 9;
+ sfixed64 optional_sfixed64 = 10;
+ float optional_float = 11;
+ double optional_double = 12;
+ bool optional_bool = 13;
+ string optional_string = 14;
+ bytes optional_bytes = 15;
+ // No 'group' in proto3.
+ Message3 optional_message = 18;
+ Enum optional_enum = 19;
+
+ repeated int32 repeated_int32 = 31;
+ repeated int64 repeated_int64 = 32;
+ repeated uint32 repeated_uint32 = 33;
+ repeated uint64 repeated_uint64 = 34;
+ repeated sint32 repeated_sint32 = 35;
+ repeated sint64 repeated_sint64 = 36;
+ repeated fixed32 repeated_fixed32 = 37;
+ repeated fixed64 repeated_fixed64 = 38;
+ repeated sfixed32 repeated_sfixed32 = 39;
+ repeated sfixed64 repeated_sfixed64 = 40;
+ repeated float repeated_float = 41;
+ repeated double repeated_double = 42;
+ repeated bool repeated_bool = 43;
+ repeated string repeated_string = 44;
+ repeated bytes repeated_bytes = 45;
+ // No 'group' in proto3.
+ repeated Message3 repeated_message = 48;
+ repeated Enum repeated_enum = 49;
+ repeated Enum repeated_packed_enum = 50 [packed=true];
+
+ oneof o {
+ int32 oneof_int32 = 51;
+ int64 oneof_int64 = 52;
+ uint32 oneof_uint32 = 53;
+ uint64 oneof_uint64 = 54;
+ sint32 oneof_sint32 = 55;
+ sint64 oneof_sint64 = 56;
+ fixed32 oneof_fixed32 = 57;
+ fixed64 oneof_fixed64 = 58;
+ sfixed32 oneof_sfixed32 = 59;
+ sfixed64 oneof_sfixed64 = 60;
+ float oneof_float = 61;
+ double oneof_double = 62;
+ bool oneof_bool = 63;
+ string oneof_string = 64;
+ bytes oneof_bytes = 65;
+ // No 'group' in proto3.
+ Message3 oneof_message = 68;
+ Enum oneof_enum = 69;
+ }
+}
diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.h b/objectivec/google/protobuf/Descriptor.pbobjc.h
new file mode 100644
index 00000000..7b11d899
--- /dev/null
+++ b/objectivec/google/protobuf/Descriptor.pbobjc.h
@@ -0,0 +1,1046 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/descriptor.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000
+#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources.
+#endif
+
+CF_EXTERN_C_BEGIN
+
+@class GPBDescriptorProto;
+@class GPBDescriptorProto_ExtensionRange;
+@class GPBEnumDescriptorProto;
+@class GPBEnumOptions;
+@class GPBEnumValueDescriptorProto;
+@class GPBEnumValueOptions;
+@class GPBFieldDescriptorProto;
+@class GPBFieldOptions;
+@class GPBFileDescriptorProto;
+@class GPBFileDescriptorSet;
+@class GPBFileOptions;
+@class GPBMessageOptions;
+@class GPBMethodDescriptorProto;
+@class GPBMethodOptions;
+@class GPBOneofDescriptorProto;
+@class GPBServiceDescriptorProto;
+@class GPBServiceOptions;
+@class GPBSourceCodeInfo;
+@class GPBSourceCodeInfo_Location;
+@class GPBUninterpretedOption;
+@class GPBUninterpretedOption_NamePart;
+
+#pragma mark - Enum GPBFieldDescriptorProto_Type
+
+typedef GPB_ENUM(GPBFieldDescriptorProto_Type) {
+ // 0 is reserved for errors.
+ // Order is weird for historical reasons.
+ GPBFieldDescriptorProto_Type_TypeDouble = 1,
+ GPBFieldDescriptorProto_Type_TypeFloat = 2,
+
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT64 if
+ // negative values are likely.
+ GPBFieldDescriptorProto_Type_TypeInt64 = 3,
+ GPBFieldDescriptorProto_Type_TypeUint64 = 4,
+
+ // Not ZigZag encoded. Negative numbers take 10 bytes. Use TYPE_SINT32 if
+ // negative values are likely.
+ GPBFieldDescriptorProto_Type_TypeInt32 = 5,
+ GPBFieldDescriptorProto_Type_TypeFixed64 = 6,
+ GPBFieldDescriptorProto_Type_TypeFixed32 = 7,
+ GPBFieldDescriptorProto_Type_TypeBool = 8,
+ GPBFieldDescriptorProto_Type_TypeString = 9,
+
+ // Tag-delimited aggregate.
+ GPBFieldDescriptorProto_Type_TypeGroup = 10,
+
+ // Length-delimited aggregate.
+ GPBFieldDescriptorProto_Type_TypeMessage = 11,
+
+ // New in version 2.
+ GPBFieldDescriptorProto_Type_TypeBytes = 12,
+ GPBFieldDescriptorProto_Type_TypeUint32 = 13,
+ GPBFieldDescriptorProto_Type_TypeEnum = 14,
+ GPBFieldDescriptorProto_Type_TypeSfixed32 = 15,
+ GPBFieldDescriptorProto_Type_TypeSfixed64 = 16,
+
+ // Uses ZigZag encoding.
+ GPBFieldDescriptorProto_Type_TypeSint32 = 17,
+
+ // Uses ZigZag encoding.
+ GPBFieldDescriptorProto_Type_TypeSint64 = 18,
+};
+
+GPBEnumDescriptor *GPBFieldDescriptorProto_Type_EnumDescriptor(void);
+
+BOOL GPBFieldDescriptorProto_Type_IsValidValue(int32_t value);
+
+#pragma mark - Enum GPBFieldDescriptorProto_Label
+
+typedef GPB_ENUM(GPBFieldDescriptorProto_Label) {
+ // 0 is reserved for errors
+ GPBFieldDescriptorProto_Label_LabelOptional = 1,
+ GPBFieldDescriptorProto_Label_LabelRequired = 2,
+
+ // TODO(sanjay): Should we add LABEL_MAP?
+ GPBFieldDescriptorProto_Label_LabelRepeated = 3,
+};
+
+GPBEnumDescriptor *GPBFieldDescriptorProto_Label_EnumDescriptor(void);
+
+BOOL GPBFieldDescriptorProto_Label_IsValidValue(int32_t value);
+
+#pragma mark - Enum GPBFileOptions_OptimizeMode
+
+// Generated classes can be optimized for speed or code size.
+typedef GPB_ENUM(GPBFileOptions_OptimizeMode) {
+ // Generate complete code for parsing, serialization,
+ GPBFileOptions_OptimizeMode_Speed = 1,
+
+ // etc.
+ GPBFileOptions_OptimizeMode_CodeSize = 2,
+
+ // Generate code using MessageLite and the lite runtime.
+ GPBFileOptions_OptimizeMode_LiteRuntime = 3,
+};
+
+GPBEnumDescriptor *GPBFileOptions_OptimizeMode_EnumDescriptor(void);
+
+BOOL GPBFileOptions_OptimizeMode_IsValidValue(int32_t value);
+
+#pragma mark - Enum GPBFieldOptions_CType
+
+typedef GPB_ENUM(GPBFieldOptions_CType) {
+ // Default mode.
+ GPBFieldOptions_CType_String = 0,
+ GPBFieldOptions_CType_Cord = 1,
+ GPBFieldOptions_CType_StringPiece = 2,
+};
+
+GPBEnumDescriptor *GPBFieldOptions_CType_EnumDescriptor(void);
+
+BOOL GPBFieldOptions_CType_IsValidValue(int32_t value);
+
+
+#pragma mark - GPBDescriptorRoot
+
+@interface GPBDescriptorRoot : GPBRootObject
+@end
+
+#pragma mark - GPBFileDescriptorSet
+
+typedef GPB_ENUM(GPBFileDescriptorSet_FieldNumber) {
+ GPBFileDescriptorSet_FieldNumber_FileArray = 1,
+};
+
+// The protocol compiler can output a FileDescriptorSet containing the .proto
+// files it parses.
+@interface GPBFileDescriptorSet : GPBMessage
+
+// |fileArray| contains |GPBFileDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *fileArray;
+
+@end
+
+#pragma mark - GPBFileDescriptorProto
+
+typedef GPB_ENUM(GPBFileDescriptorProto_FieldNumber) {
+ GPBFileDescriptorProto_FieldNumber_Name = 1,
+ GPBFileDescriptorProto_FieldNumber_Package = 2,
+ GPBFileDescriptorProto_FieldNumber_DependencyArray = 3,
+ GPBFileDescriptorProto_FieldNumber_MessageTypeArray = 4,
+ GPBFileDescriptorProto_FieldNumber_EnumTypeArray = 5,
+ GPBFileDescriptorProto_FieldNumber_ServiceArray = 6,
+ GPBFileDescriptorProto_FieldNumber_ExtensionArray = 7,
+ GPBFileDescriptorProto_FieldNumber_Options = 8,
+ GPBFileDescriptorProto_FieldNumber_SourceCodeInfo = 9,
+ GPBFileDescriptorProto_FieldNumber_PublicDependencyArray = 10,
+ GPBFileDescriptorProto_FieldNumber_WeakDependencyArray = 11,
+ GPBFileDescriptorProto_FieldNumber_Syntax = 12,
+};
+
+// Describes a complete .proto file.
+@interface GPBFileDescriptorProto : GPBMessage
+
+// file name, relative to root of source tree
+@property(nonatomic, readwrite) BOOL hasName;
+@property(nonatomic, readwrite, copy) NSString *name;
+
+// e.g. "foo", "foo.bar", etc.
+@property(nonatomic, readwrite) BOOL hasPackage;
+@property(nonatomic, readwrite, copy) NSString *package;
+
+// Names of files imported by this file.
+// |dependencyArray| contains |NSString|
+@property(nonatomic, readwrite, strong) NSMutableArray *dependencyArray;
+
+// Indexes of the public imported files in the dependency list above.
+@property(nonatomic, readwrite, strong) GPBInt32Array *publicDependencyArray;
+
+// Indexes of the weak imported files in the dependency list.
+// For Google-internal migration only. Do not use.
+@property(nonatomic, readwrite, strong) GPBInt32Array *weakDependencyArray;
+
+// All top-level definitions in this file.
+// |messageTypeArray| contains |GPBDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *messageTypeArray;
+
+// |enumTypeArray| contains |GPBEnumDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *enumTypeArray;
+
+// |serviceArray| contains |GPBServiceDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *serviceArray;
+
+// |extensionArray| contains |GPBFieldDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *extensionArray;
+
+@property(nonatomic, readwrite) BOOL hasOptions;
+@property(nonatomic, readwrite, strong) GPBFileOptions *options;
+
+// This field contains optional information about the original source code.
+// You may safely remove this entire field without harming runtime
+// functionality of the descriptors -- the information is needed only by
+// development tools.
+@property(nonatomic, readwrite) BOOL hasSourceCodeInfo;
+@property(nonatomic, readwrite, strong) GPBSourceCodeInfo *sourceCodeInfo;
+
+// The syntax of the proto file.
+// The supported values are "proto2" and "proto3".
+@property(nonatomic, readwrite) BOOL hasSyntax;
+@property(nonatomic, readwrite, copy) NSString *syntax;
+
+@end
+
+#pragma mark - GPBDescriptorProto
+
+typedef GPB_ENUM(GPBDescriptorProto_FieldNumber) {
+ GPBDescriptorProto_FieldNumber_Name = 1,
+ GPBDescriptorProto_FieldNumber_FieldArray = 2,
+ GPBDescriptorProto_FieldNumber_NestedTypeArray = 3,
+ GPBDescriptorProto_FieldNumber_EnumTypeArray = 4,
+ GPBDescriptorProto_FieldNumber_ExtensionRangeArray = 5,
+ GPBDescriptorProto_FieldNumber_ExtensionArray = 6,
+ GPBDescriptorProto_FieldNumber_Options = 7,
+ GPBDescriptorProto_FieldNumber_OneofDeclArray = 8,
+};
+
+// Describes a message type.
+@interface GPBDescriptorProto : GPBMessage
+
+@property(nonatomic, readwrite) BOOL hasName;
+@property(nonatomic, readwrite, copy) NSString *name;
+
+// |fieldArray| contains |GPBFieldDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *fieldArray;
+
+// |extensionArray| contains |GPBFieldDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *extensionArray;
+
+// |nestedTypeArray| contains |GPBDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *nestedTypeArray;
+
+// |enumTypeArray| contains |GPBEnumDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *enumTypeArray;
+
+// |extensionRangeArray| contains |GPBDescriptorProto_ExtensionRange|
+@property(nonatomic, readwrite, strong) NSMutableArray *extensionRangeArray;
+
+// |oneofDeclArray| contains |GPBOneofDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *oneofDeclArray;
+
+@property(nonatomic, readwrite) BOOL hasOptions;
+@property(nonatomic, readwrite, strong) GPBMessageOptions *options;
+
+@end
+
+#pragma mark - GPBDescriptorProto_ExtensionRange
+
+typedef GPB_ENUM(GPBDescriptorProto_ExtensionRange_FieldNumber) {
+ GPBDescriptorProto_ExtensionRange_FieldNumber_Start = 1,
+ GPBDescriptorProto_ExtensionRange_FieldNumber_End = 2,
+};
+
+@interface GPBDescriptorProto_ExtensionRange : GPBMessage
+
+@property(nonatomic, readwrite) BOOL hasStart;
+@property(nonatomic, readwrite) int32_t start;
+
+@property(nonatomic, readwrite) BOOL hasEnd;
+@property(nonatomic, readwrite) int32_t end;
+
+@end
+
+#pragma mark - GPBFieldDescriptorProto
+
+typedef GPB_ENUM(GPBFieldDescriptorProto_FieldNumber) {
+ GPBFieldDescriptorProto_FieldNumber_Name = 1,
+ GPBFieldDescriptorProto_FieldNumber_Extendee = 2,
+ GPBFieldDescriptorProto_FieldNumber_Number = 3,
+ GPBFieldDescriptorProto_FieldNumber_Label = 4,
+ GPBFieldDescriptorProto_FieldNumber_Type = 5,
+ GPBFieldDescriptorProto_FieldNumber_TypeName = 6,
+ GPBFieldDescriptorProto_FieldNumber_DefaultValue = 7,
+ GPBFieldDescriptorProto_FieldNumber_Options = 8,
+ GPBFieldDescriptorProto_FieldNumber_OneofIndex = 9,
+};
+
+// Describes a field within a message.
+@interface GPBFieldDescriptorProto : GPBMessage
+
+@property(nonatomic, readwrite) BOOL hasName;
+@property(nonatomic, readwrite, copy) NSString *name;
+
+@property(nonatomic, readwrite) BOOL hasNumber;
+@property(nonatomic, readwrite) int32_t number;
+
+@property(nonatomic, readwrite) BOOL hasLabel;
+@property(nonatomic, readwrite) GPBFieldDescriptorProto_Label label;
+
+// If type_name is set, this need not be set. If both this and type_name
+// are set, this must be one of TYPE_ENUM, TYPE_MESSAGE or TYPE_GROUP.
+@property(nonatomic, readwrite) BOOL hasType;
+@property(nonatomic, readwrite) GPBFieldDescriptorProto_Type type;
+
+// For message and enum types, this is the name of the type. If the name
+// starts with a '.', it is fully-qualified. Otherwise, C++-like scoping
+// rules are used to find the type (i.e. first the nested types within this
+// message are searched, then within the parent, on up to the root
+// namespace).
+@property(nonatomic, readwrite) BOOL hasTypeName;
+@property(nonatomic, readwrite, copy) NSString *typeName;
+
+// For extensions, this is the name of the type being extended. It is
+// resolved in the same manner as type_name.
+@property(nonatomic, readwrite) BOOL hasExtendee;
+@property(nonatomic, readwrite, copy) NSString *extendee;
+
+// For numeric types, contains the original text representation of the value.
+// For booleans, "true" or "false".
+// For strings, contains the default text contents (not escaped in any way).
+// For bytes, contains the C escaped value. All bytes >= 128 are escaped.
+// TODO(kenton): Base-64 encode?
+@property(nonatomic, readwrite) BOOL hasDefaultValue;
+@property(nonatomic, readwrite, copy) NSString *defaultValue;
+
+// If set, gives the index of a oneof in the containing type's oneof_decl
+// list. This field is a member of that oneof.
+@property(nonatomic, readwrite) BOOL hasOneofIndex;
+@property(nonatomic, readwrite) int32_t oneofIndex;
+
+@property(nonatomic, readwrite) BOOL hasOptions;
+@property(nonatomic, readwrite, strong) GPBFieldOptions *options;
+
+@end
+
+#pragma mark - GPBOneofDescriptorProto
+
+typedef GPB_ENUM(GPBOneofDescriptorProto_FieldNumber) {
+ GPBOneofDescriptorProto_FieldNumber_Name = 1,
+};
+
+// Describes a oneof.
+@interface GPBOneofDescriptorProto : GPBMessage
+
+@property(nonatomic, readwrite) BOOL hasName;
+@property(nonatomic, readwrite, copy) NSString *name;
+
+@end
+
+#pragma mark - GPBEnumDescriptorProto
+
+typedef GPB_ENUM(GPBEnumDescriptorProto_FieldNumber) {
+ GPBEnumDescriptorProto_FieldNumber_Name = 1,
+ GPBEnumDescriptorProto_FieldNumber_ValueArray = 2,
+ GPBEnumDescriptorProto_FieldNumber_Options = 3,
+};
+
+// Describes an enum type.
+@interface GPBEnumDescriptorProto : GPBMessage
+
+@property(nonatomic, readwrite) BOOL hasName;
+@property(nonatomic, readwrite, copy) NSString *name;
+
+// |valueArray| contains |GPBEnumValueDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *valueArray;
+
+@property(nonatomic, readwrite) BOOL hasOptions;
+@property(nonatomic, readwrite, strong) GPBEnumOptions *options;
+
+@end
+
+#pragma mark - GPBEnumValueDescriptorProto
+
+typedef GPB_ENUM(GPBEnumValueDescriptorProto_FieldNumber) {
+ GPBEnumValueDescriptorProto_FieldNumber_Name = 1,
+ GPBEnumValueDescriptorProto_FieldNumber_Number = 2,
+ GPBEnumValueDescriptorProto_FieldNumber_Options = 3,
+};
+
+// Describes a value within an enum.
+@interface GPBEnumValueDescriptorProto : GPBMessage
+
+@property(nonatomic, readwrite) BOOL hasName;
+@property(nonatomic, readwrite, copy) NSString *name;
+
+@property(nonatomic, readwrite) BOOL hasNumber;
+@property(nonatomic, readwrite) int32_t number;
+
+@property(nonatomic, readwrite) BOOL hasOptions;
+@property(nonatomic, readwrite, strong) GPBEnumValueOptions *options;
+
+@end
+
+#pragma mark - GPBServiceDescriptorProto
+
+typedef GPB_ENUM(GPBServiceDescriptorProto_FieldNumber) {
+ GPBServiceDescriptorProto_FieldNumber_Name = 1,
+ GPBServiceDescriptorProto_FieldNumber_MethodArray = 2,
+ GPBServiceDescriptorProto_FieldNumber_Options = 3,
+};
+
+// Describes a service.
+@interface GPBServiceDescriptorProto : GPBMessage
+
+@property(nonatomic, readwrite) BOOL hasName;
+@property(nonatomic, readwrite, copy) NSString *name;
+
+// |methodArray| contains |GPBMethodDescriptorProto|
+@property(nonatomic, readwrite, strong) NSMutableArray *methodArray;
+
+@property(nonatomic, readwrite) BOOL hasOptions;
+@property(nonatomic, readwrite, strong) GPBServiceOptions *options;
+
+@end
+
+#pragma mark - GPBMethodDescriptorProto
+
+typedef GPB_ENUM(GPBMethodDescriptorProto_FieldNumber) {
+ GPBMethodDescriptorProto_FieldNumber_Name = 1,
+ GPBMethodDescriptorProto_FieldNumber_InputType = 2,
+ GPBMethodDescriptorProto_FieldNumber_OutputType = 3,
+ GPBMethodDescriptorProto_FieldNumber_Options = 4,
+ GPBMethodDescriptorProto_FieldNumber_ClientStreaming = 5,
+ GPBMethodDescriptorProto_FieldNumber_ServerStreaming = 6,
+};
+
+// Describes a method of a service.
+@interface GPBMethodDescriptorProto : GPBMessage
+
+@property(nonatomic, readwrite) BOOL hasName;
+@property(nonatomic, readwrite, copy) NSString *name;
+
+// Input and output type names. These are resolved in the same way as
+// FieldDescriptorProto.type_name, but must refer to a message type.
+@property(nonatomic, readwrite) BOOL hasInputType;
+@property(nonatomic, readwrite, copy) NSString *inputType;
+
+@property(nonatomic, readwrite) BOOL hasOutputType;
+@property(nonatomic, readwrite, copy) NSString *outputType;
+
+@property(nonatomic, readwrite) BOOL hasOptions;
+@property(nonatomic, readwrite, strong) GPBMethodOptions *options;
+
+// Identifies if client streams multiple client messages
+@property(nonatomic, readwrite) BOOL hasClientStreaming;
+@property(nonatomic, readwrite) BOOL clientStreaming;
+
+// Identifies if server streams multiple server messages
+@property(nonatomic, readwrite) BOOL hasServerStreaming;
+@property(nonatomic, readwrite) BOOL serverStreaming;
+
+@end
+
+#pragma mark - GPBFileOptions
+
+typedef GPB_ENUM(GPBFileOptions_FieldNumber) {
+ GPBFileOptions_FieldNumber_JavaPackage = 1,
+ GPBFileOptions_FieldNumber_JavaOuterClassname = 8,
+ GPBFileOptions_FieldNumber_OptimizeFor = 9,
+ GPBFileOptions_FieldNumber_JavaMultipleFiles = 10,
+ GPBFileOptions_FieldNumber_GoPackage = 11,
+ GPBFileOptions_FieldNumber_CcGenericServices = 16,
+ GPBFileOptions_FieldNumber_JavaGenericServices = 17,
+ GPBFileOptions_FieldNumber_PyGenericServices = 18,
+ GPBFileOptions_FieldNumber_JavaGenerateEqualsAndHash = 20,
+ GPBFileOptions_FieldNumber_Deprecated = 23,
+ GPBFileOptions_FieldNumber_JavaStringCheckUtf8 = 27,
+ GPBFileOptions_FieldNumber_CcEnableArenas = 31,
+ GPBFileOptions_FieldNumber_ObjcClassPrefix = 36,
+ GPBFileOptions_FieldNumber_UninterpretedOptionArray = 999,
+};
+
+@interface GPBFileOptions : GPBMessage
+
+// Sets the Java package where classes generated from this .proto will be
+// placed. By default, the proto package is used, but this is often
+// inappropriate because proto packages do not normally start with backwards
+// domain names.
+@property(nonatomic, readwrite) BOOL hasJavaPackage;
+@property(nonatomic, readwrite, copy) NSString *javaPackage;
+
+// If set, all the classes from the .proto file are wrapped in a single
+// outer class with the given name. This applies to both Proto1
+// (equivalent to the old "--one_java_file" option) and Proto2 (where
+// a .proto always translates to a single class, but you may want to
+// explicitly choose the class name).
+@property(nonatomic, readwrite) BOOL hasJavaOuterClassname;
+@property(nonatomic, readwrite, copy) NSString *javaOuterClassname;
+
+// If set true, then the Java code generator will generate a separate .java
+// file for each top-level message, enum, and service defined in the .proto
+// file. Thus, these types will *not* be nested inside the outer class
+// named by java_outer_classname. However, the outer class will still be
+// generated to contain the file's getDescriptor() method as well as any
+// top-level extensions defined in the file.
+@property(nonatomic, readwrite) BOOL hasJavaMultipleFiles;
+@property(nonatomic, readwrite) BOOL javaMultipleFiles;
+
+// If set true, then the Java code generator will generate equals() and
+// hashCode() methods for all messages defined in the .proto file.
+// - In the full runtime, this is purely a speed optimization, as the
+// AbstractMessage base class includes reflection-based implementations of
+// these methods.
+//- In the lite runtime, setting this option changes the semantics of
+// equals() and hashCode() to more closely match those of the full runtime;
+// the generated methods compute their results based on field values rather
+// than object identity. (Implementations should not assume that hashcodes
+// will be consistent across runtimes or versions of the protocol compiler.)
+@property(nonatomic, readwrite) BOOL hasJavaGenerateEqualsAndHash;
+@property(nonatomic, readwrite) BOOL javaGenerateEqualsAndHash;
+
+// If set true, then the Java2 code generator will generate code that
+// throws an exception whenever an attempt is made to assign a non-UTF-8
+// byte sequence to a string field.
+// Message reflection will do the same.
+// However, an extension field still accepts non-UTF-8 byte sequences.
+// This option has no effect on when used with the lite runtime.
+@property(nonatomic, readwrite) BOOL hasJavaStringCheckUtf8;
+@property(nonatomic, readwrite) BOOL javaStringCheckUtf8;
+
+@property(nonatomic, readwrite) BOOL hasOptimizeFor;
+@property(nonatomic, readwrite) GPBFileOptions_OptimizeMode optimizeFor;
+
+// Sets the Go package where structs generated from this .proto will be
+// placed. If omitted, the Go package will be derived from the following:
+// - The basename of the package import path, if provided.
+// - Otherwise, the package statement in the .proto file, if present.
+// - Otherwise, the basename of the .proto file, without extension.
+@property(nonatomic, readwrite) BOOL hasGoPackage;
+@property(nonatomic, readwrite, copy) NSString *goPackage;
+
+// Should generic services be generated in each language? "Generic" services
+// are not specific to any particular RPC system. They are generated by the
+// main code generators in each language (without additional plugins).
+// Generic services were the only kind of service generation supported by
+// early versions of google.protobuf.
+//
+// Generic services are now considered deprecated in favor of using plugins
+// that generate code specific to your particular RPC system. Therefore,
+// these default to false. Old code which depends on generic services should
+// explicitly set them to true.
+@property(nonatomic, readwrite) BOOL hasCcGenericServices;
+@property(nonatomic, readwrite) BOOL ccGenericServices;
+
+@property(nonatomic, readwrite) BOOL hasJavaGenericServices;
+@property(nonatomic, readwrite) BOOL javaGenericServices;
+
+@property(nonatomic, readwrite) BOOL hasPyGenericServices;
+@property(nonatomic, readwrite) BOOL pyGenericServices;
+
+// Is this file deprecated?
+// Depending on the target platform, this can emit Deprecated annotations
+// for everything in the file, or it will be completely ignored; in the very
+// least, this is a formalization for deprecating files.
+@property(nonatomic, readwrite) BOOL hasDeprecated;
+@property(nonatomic, readwrite) BOOL deprecated;
+
+// Enables the use of arenas for the proto messages in this file. This applies
+// only to generated classes for C++.
+@property(nonatomic, readwrite) BOOL hasCcEnableArenas;
+@property(nonatomic, readwrite) BOOL ccEnableArenas;
+
+// Sets the objective c class prefix which is prepended to all objective c
+// generated classes from this .proto. There is no default.
+@property(nonatomic, readwrite) BOOL hasObjcClassPrefix;
+@property(nonatomic, readwrite, copy) NSString *objcClassPrefix;
+
+// The parser stores options it doesn't recognize here. See above.
+// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
+@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+
+@end
+
+#pragma mark - GPBMessageOptions
+
+typedef GPB_ENUM(GPBMessageOptions_FieldNumber) {
+ GPBMessageOptions_FieldNumber_MessageSetWireFormat = 1,
+ GPBMessageOptions_FieldNumber_NoStandardDescriptorAccessor = 2,
+ GPBMessageOptions_FieldNumber_Deprecated = 3,
+ GPBMessageOptions_FieldNumber_MapEntry = 7,
+ GPBMessageOptions_FieldNumber_UninterpretedOptionArray = 999,
+};
+
+@interface GPBMessageOptions : GPBMessage
+
+// Set true to use the old proto1 MessageSet wire format for extensions.
+// This is provided for backwards-compatibility with the MessageSet wire
+// format. You should not use this for any other reason: It's less
+// efficient, has fewer features, and is more complicated.
+//
+// The message must be defined exactly as follows:
+// message Foo {
+// option message_set_wire_format = true;
+// extensions 4 to max;
+// }
+// Note that the message cannot have any defined fields; MessageSets only
+// have extensions.
+//
+// All extensions of your type must be singular messages; e.g. they cannot
+// be int32s, enums, or repeated messages.
+//
+// Because this is an option, the above two restrictions are not enforced by
+// the protocol compiler.
+@property(nonatomic, readwrite) BOOL hasMessageSetWireFormat;
+@property(nonatomic, readwrite) BOOL messageSetWireFormat;
+
+// Disables the generation of the standard "descriptor()" accessor, which can
+// conflict with a field of the same name. This is meant to make migration
+// from proto1 easier; new code should avoid fields named "descriptor".
+@property(nonatomic, readwrite) BOOL hasNoStandardDescriptorAccessor;
+@property(nonatomic, readwrite) BOOL noStandardDescriptorAccessor;
+
+// Is this message deprecated?
+// Depending on the target platform, this can emit Deprecated annotations
+// for the message, or it will be completely ignored; in the very least,
+// this is a formalization for deprecating messages.
+@property(nonatomic, readwrite) BOOL hasDeprecated;
+@property(nonatomic, readwrite) BOOL deprecated;
+
+// Whether the message is an automatically generated map entry type for the
+// maps field.
+//
+// For maps fields:
+// map<KeyType, ValueType> map_field = 1;
+// The parsed descriptor looks like:
+// message MapFieldEntry {
+// option map_entry = true;
+// optional KeyType key = 1;
+// optional ValueType value = 2;
+// }
+// repeated MapFieldEntry map_field = 1;
+//
+// Implementations may choose not to generate the map_entry=true message, but
+// use a native map in the target language to hold the keys and values.
+// The reflection APIs in such implementions still need to work as
+// if the field is a repeated message field.
+//
+// NOTE: Do not set the option in .proto files. Always use the maps syntax
+// instead. The option should only be implicitly set by the proto compiler
+// parser.
+@property(nonatomic, readwrite) BOOL hasMapEntry;
+@property(nonatomic, readwrite) BOOL mapEntry;
+
+// The parser stores options it doesn't recognize here. See above.
+// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
+@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+
+@end
+
+#pragma mark - GPBFieldOptions
+
+typedef GPB_ENUM(GPBFieldOptions_FieldNumber) {
+ GPBFieldOptions_FieldNumber_Ctype = 1,
+ GPBFieldOptions_FieldNumber_Packed = 2,
+ GPBFieldOptions_FieldNumber_Deprecated = 3,
+ GPBFieldOptions_FieldNumber_Lazy = 5,
+ GPBFieldOptions_FieldNumber_Weak = 10,
+ GPBFieldOptions_FieldNumber_UninterpretedOptionArray = 999,
+};
+
+@interface GPBFieldOptions : GPBMessage
+
+// The ctype option instructs the C++ code generator to use a different
+// representation of the field than it normally would. See the specific
+// options below. This option is not yet implemented in the open source
+// release -- sorry, we'll try to include it in a future version!
+@property(nonatomic, readwrite) BOOL hasCtype;
+@property(nonatomic, readwrite) GPBFieldOptions_CType ctype;
+
+// The packed option can be enabled for repeated primitive fields to enable
+// a more efficient representation on the wire. Rather than repeatedly
+// writing the tag and type for each element, the entire array is encoded as
+// a single length-delimited blob.
+@property(nonatomic, readwrite) BOOL hasPacked;
+@property(nonatomic, readwrite) BOOL packed;
+
+// Should this field be parsed lazily? Lazy applies only to message-type
+// fields. It means that when the outer message is initially parsed, the
+// inner message's contents will not be parsed but instead stored in encoded
+// form. The inner message will actually be parsed when it is first accessed.
+//
+// This is only a hint. Implementations are free to choose whether to use
+// eager or lazy parsing regardless of the value of this option. However,
+// setting this option true suggests that the protocol author believes that
+// using lazy parsing on this field is worth the additional bookkeeping
+// overhead typically needed to implement it.
+//
+// This option does not affect the public interface of any generated code;
+// all method signatures remain the same. Furthermore, thread-safety of the
+// interface is not affected by this option; const methods remain safe to
+// call from multiple threads concurrently, while non-const methods continue
+// to require exclusive access.
+//
+//
+// Note that implementations may choose not to check required fields within
+// a lazy sub-message. That is, calling IsInitialized() on the outher message
+// may return true even if the inner message has missing required fields.
+// This is necessary because otherwise the inner message would have to be
+// parsed in order to perform the check, defeating the purpose of lazy
+// parsing. An implementation which chooses not to check required fields
+// must be consistent about it. That is, for any particular sub-message, the
+// implementation must either *always* check its required fields, or *never*
+// check its required fields, regardless of whether or not the message has
+// been parsed.
+@property(nonatomic, readwrite) BOOL hasLazy;
+@property(nonatomic, readwrite) BOOL lazy;
+
+// Is this field deprecated?
+// Depending on the target platform, this can emit Deprecated annotations
+// for accessors, or it will be completely ignored; in the very least, this
+// is a formalization for deprecating fields.
+@property(nonatomic, readwrite) BOOL hasDeprecated;
+@property(nonatomic, readwrite) BOOL deprecated;
+
+// For Google-internal migration only. Do not use.
+@property(nonatomic, readwrite) BOOL hasWeak;
+@property(nonatomic, readwrite) BOOL weak;
+
+// The parser stores options it doesn't recognize here. See above.
+// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
+@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+
+@end
+
+#pragma mark - GPBEnumOptions
+
+typedef GPB_ENUM(GPBEnumOptions_FieldNumber) {
+ GPBEnumOptions_FieldNumber_AllowAlias = 2,
+ GPBEnumOptions_FieldNumber_Deprecated = 3,
+ GPBEnumOptions_FieldNumber_UninterpretedOptionArray = 999,
+};
+
+@interface GPBEnumOptions : GPBMessage
+
+// Set this option to true to allow mapping different tag names to the same
+// value.
+@property(nonatomic, readwrite) BOOL hasAllowAlias;
+@property(nonatomic, readwrite) BOOL allowAlias;
+
+// Is this enum deprecated?
+// Depending on the target platform, this can emit Deprecated annotations
+// for the enum, or it will be completely ignored; in the very least, this
+// is a formalization for deprecating enums.
+@property(nonatomic, readwrite) BOOL hasDeprecated;
+@property(nonatomic, readwrite) BOOL deprecated;
+
+// The parser stores options it doesn't recognize here. See above.
+// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
+@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+
+@end
+
+#pragma mark - GPBEnumValueOptions
+
+typedef GPB_ENUM(GPBEnumValueOptions_FieldNumber) {
+ GPBEnumValueOptions_FieldNumber_Deprecated = 1,
+ GPBEnumValueOptions_FieldNumber_UninterpretedOptionArray = 999,
+};
+
+@interface GPBEnumValueOptions : GPBMessage
+
+// Is this enum value deprecated?
+// Depending on the target platform, this can emit Deprecated annotations
+// for the enum value, or it will be completely ignored; in the very least,
+// this is a formalization for deprecating enum values.
+@property(nonatomic, readwrite) BOOL hasDeprecated;
+@property(nonatomic, readwrite) BOOL deprecated;
+
+// The parser stores options it doesn't recognize here. See above.
+// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
+@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+
+@end
+
+#pragma mark - GPBServiceOptions
+
+typedef GPB_ENUM(GPBServiceOptions_FieldNumber) {
+ GPBServiceOptions_FieldNumber_Deprecated = 33,
+ GPBServiceOptions_FieldNumber_UninterpretedOptionArray = 999,
+};
+
+@interface GPBServiceOptions : GPBMessage
+
+// Is this service deprecated?
+// Depending on the target platform, this can emit Deprecated annotations
+// for the service, or it will be completely ignored; in the very least,
+// this is a formalization for deprecating services.
+@property(nonatomic, readwrite) BOOL hasDeprecated;
+@property(nonatomic, readwrite) BOOL deprecated;
+
+// The parser stores options it doesn't recognize here. See above.
+// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
+@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+
+@end
+
+#pragma mark - GPBMethodOptions
+
+typedef GPB_ENUM(GPBMethodOptions_FieldNumber) {
+ GPBMethodOptions_FieldNumber_Deprecated = 33,
+ GPBMethodOptions_FieldNumber_UninterpretedOptionArray = 999,
+};
+
+@interface GPBMethodOptions : GPBMessage
+
+// Is this method deprecated?
+// Depending on the target platform, this can emit Deprecated annotations
+// for the method, or it will be completely ignored; in the very least,
+// this is a formalization for deprecating methods.
+@property(nonatomic, readwrite) BOOL hasDeprecated;
+@property(nonatomic, readwrite) BOOL deprecated;
+
+// The parser stores options it doesn't recognize here. See above.
+// |uninterpretedOptionArray| contains |GPBUninterpretedOption|
+@property(nonatomic, readwrite, strong) NSMutableArray *uninterpretedOptionArray;
+
+@end
+
+#pragma mark - GPBUninterpretedOption
+
+typedef GPB_ENUM(GPBUninterpretedOption_FieldNumber) {
+ GPBUninterpretedOption_FieldNumber_NameArray = 2,
+ GPBUninterpretedOption_FieldNumber_IdentifierValue = 3,
+ GPBUninterpretedOption_FieldNumber_PositiveIntValue = 4,
+ GPBUninterpretedOption_FieldNumber_NegativeIntValue = 5,
+ GPBUninterpretedOption_FieldNumber_DoubleValue = 6,
+ GPBUninterpretedOption_FieldNumber_StringValue = 7,
+ GPBUninterpretedOption_FieldNumber_AggregateValue = 8,
+};
+
+// A message representing a option the parser does not recognize. This only
+// appears in options protos created by the compiler::Parser class.
+// DescriptorPool resolves these when building Descriptor objects. Therefore,
+// options protos in descriptor objects (e.g. returned by Descriptor::options(),
+// or produced by Descriptor::CopyTo()) will never have UninterpretedOptions
+// in them.
+@interface GPBUninterpretedOption : GPBMessage
+
+// |nameArray| contains |GPBUninterpretedOption_NamePart|
+@property(nonatomic, readwrite, strong) NSMutableArray *nameArray;
+
+// The value of the uninterpreted option, in whatever type the tokenizer
+// identified it as during parsing. Exactly one of these should be set.
+@property(nonatomic, readwrite) BOOL hasIdentifierValue;
+@property(nonatomic, readwrite, copy) NSString *identifierValue;
+
+@property(nonatomic, readwrite) BOOL hasPositiveIntValue;
+@property(nonatomic, readwrite) uint64_t positiveIntValue;
+
+@property(nonatomic, readwrite) BOOL hasNegativeIntValue;
+@property(nonatomic, readwrite) int64_t negativeIntValue;
+
+@property(nonatomic, readwrite) BOOL hasDoubleValue;
+@property(nonatomic, readwrite) double doubleValue;
+
+@property(nonatomic, readwrite) BOOL hasStringValue;
+@property(nonatomic, readwrite, copy) NSData *stringValue;
+
+@property(nonatomic, readwrite) BOOL hasAggregateValue;
+@property(nonatomic, readwrite, copy) NSString *aggregateValue;
+
+@end
+
+#pragma mark - GPBUninterpretedOption_NamePart
+
+typedef GPB_ENUM(GPBUninterpretedOption_NamePart_FieldNumber) {
+ GPBUninterpretedOption_NamePart_FieldNumber_NamePart = 1,
+ GPBUninterpretedOption_NamePart_FieldNumber_IsExtension = 2,
+};
+
+// The name of the uninterpreted option. Each string represents a segment in
+// a dot-separated name. is_extension is true iff a segment represents an
+// extension (denoted with parentheses in options specs in .proto files).
+// E.g.,{ ["foo", false], ["bar.baz", true], ["qux", false] } represents
+// "foo.(bar.baz).qux".
+@interface GPBUninterpretedOption_NamePart : GPBMessage
+
+@property(nonatomic, readwrite) BOOL hasNamePart;
+@property(nonatomic, readwrite, copy) NSString *namePart;
+
+@property(nonatomic, readwrite) BOOL hasIsExtension;
+@property(nonatomic, readwrite) BOOL isExtension;
+
+@end
+
+#pragma mark - GPBSourceCodeInfo
+
+typedef GPB_ENUM(GPBSourceCodeInfo_FieldNumber) {
+ GPBSourceCodeInfo_FieldNumber_LocationArray = 1,
+};
+
+// Encapsulates information about the original source file from which a
+// FileDescriptorProto was generated.
+@interface GPBSourceCodeInfo : GPBMessage
+
+// A Location identifies a piece of source code in a .proto file which
+// corresponds to a particular definition. This information is intended
+// to be useful to IDEs, code indexers, documentation generators, and similar
+// tools.
+//
+// For example, say we have a file like:
+// message Foo {
+// optional string foo = 1;
+// }
+// Let's look at just the field definition:
+// optional string foo = 1;
+// ^ ^^ ^^ ^ ^^^
+// a bc de f ghi
+// We have the following locations:
+// span path represents
+// [a,i) [ 4, 0, 2, 0 ] The whole field definition.
+// [a,b) [ 4, 0, 2, 0, 4 ] The label (optional).
+// [c,d) [ 4, 0, 2, 0, 5 ] The type (string).
+// [e,f) [ 4, 0, 2, 0, 1 ] The name (foo).
+// [g,h) [ 4, 0, 2, 0, 3 ] The number (1).
+//
+// Notes:
+// - A location may refer to a repeated field itself (i.e. not to any
+// particular index within it). This is used whenever a set of elements are
+// logically enclosed in a single code segment. For example, an entire
+// extend block (possibly containing multiple extension definitions) will
+// have an outer location whose path refers to the "extensions" repeated
+// field without an index.
+// - Multiple locations may have the same path. This happens when a single
+// logical declaration is spread out across multiple places. The most
+// obvious example is the "extend" block again -- there may be multiple
+// extend blocks in the same scope, each of which will have the same path.
+// - A location's span is not always a subset of its parent's span. For
+// example, the "extendee" of an extension declaration appears at the
+// beginning of the "extend" block and is shared by all extensions within
+// the block.
+// - Just because a location's span is a subset of some other location's span
+// does not mean that it is a descendent. For example, a "group" defines
+// both a type and a field in a single declaration. Thus, the locations
+// corresponding to the type and field and their components will overlap.
+// - Code which tries to interpret locations should probably be designed to
+// ignore those that it doesn't understand, as more types of locations could
+// be recorded in the future.
+// |locationArray| contains |GPBSourceCodeInfo_Location|
+@property(nonatomic, readwrite, strong) NSMutableArray *locationArray;
+
+@end
+
+#pragma mark - GPBSourceCodeInfo_Location
+
+typedef GPB_ENUM(GPBSourceCodeInfo_Location_FieldNumber) {
+ GPBSourceCodeInfo_Location_FieldNumber_PathArray = 1,
+ GPBSourceCodeInfo_Location_FieldNumber_SpanArray = 2,
+ GPBSourceCodeInfo_Location_FieldNumber_LeadingComments = 3,
+ GPBSourceCodeInfo_Location_FieldNumber_TrailingComments = 4,
+ GPBSourceCodeInfo_Location_FieldNumber_LeadingDetachedCommentsArray = 6,
+};
+
+@interface GPBSourceCodeInfo_Location : GPBMessage
+
+// Identifies which part of the FileDescriptorProto was defined at this
+// location.
+//
+// Each element is a field number or an index. They form a path from
+// the root FileDescriptorProto to the place where the definition. For
+// example, this path:
+// [ 4, 3, 2, 7, 1 ]
+// refers to:
+// file.message_type(3) // 4, 3
+// .field(7) // 2, 7
+// .name() // 1
+// This is because FileDescriptorProto.message_type has field number 4:
+// repeated DescriptorProto message_type = 4;
+// and DescriptorProto.field has field number 2:
+// repeated FieldDescriptorProto field = 2;
+// and FieldDescriptorProto.name has field number 1:
+// optional string name = 1;
+//
+// Thus, the above path gives the location of a field name. If we removed
+// the last element:
+// [ 4, 3, 2, 7 ]
+// this path refers to the whole field declaration (from the beginning
+// of the label to the terminating semicolon).
+@property(nonatomic, readwrite, strong) GPBInt32Array *pathArray;
+
+// Always has exactly three or four elements: start line, start column,
+// end line (optional, otherwise assumed same as start line), end column.
+// These are packed into a single field for efficiency. Note that line
+// and column numbers are zero-based -- typically you will want to add
+// 1 to each before displaying to a user.
+@property(nonatomic, readwrite, strong) GPBInt32Array *spanArray;
+
+// If this SourceCodeInfo represents a complete declaration, these are any
+// comments appearing before and after the declaration which appear to be
+// attached to the declaration.
+//
+// A series of line comments appearing on consecutive lines, with no other
+// tokens appearing on those lines, will be treated as a single comment.
+//
+// leading_detached_comments will keep paragraphs of comments that appear
+// before (but not connected to) the current element. Each paragraph,
+// separated by empty lines, will be one comment element in the repeated
+// field.
+//
+// Only the comment content is provided; comment markers (e.g. //) are
+// stripped out. For block comments, leading whitespace and an asterisk
+// will be stripped from the beginning of each line other than the first.
+// Newlines are included in the output.
+//
+// Examples:
+//
+// optional int32 foo = 1; // Comment attached to foo.
+// // Comment attached to bar.
+// optional int32 bar = 2;
+//
+// optional string baz = 3;
+// // Comment attached to baz.
+// // Another line attached to baz.
+//
+// // Comment attached to qux.
+// //
+// // Another line attached to qux.
+// optional double qux = 4;
+//
+// // Detached comment for corge. This is not leading or trailing comments
+// // to qux or corge because there are blank lines separating it from
+// // both.
+//
+// // Detached comment for corge paragraph 2.
+//
+// optional string corge = 5;
+// /* Block comment attached
+// * to corge. Leading asterisks
+// * will be removed. */
+// /* Block comment attached to
+// * grault. */
+// optional int32 grault = 6;
+//
+// // ignored detached comments.
+@property(nonatomic, readwrite) BOOL hasLeadingComments;
+@property(nonatomic, readwrite, copy) NSString *leadingComments;
+
+@property(nonatomic, readwrite) BOOL hasTrailingComments;
+@property(nonatomic, readwrite, copy) NSString *trailingComments;
+
+// |leadingDetachedCommentsArray| contains |NSString|
+@property(nonatomic, readwrite, strong) NSMutableArray *leadingDetachedCommentsArray;
+
+@end
+
+CF_EXTERN_C_END
diff --git a/objectivec/google/protobuf/Descriptor.pbobjc.m b/objectivec/google/protobuf/Descriptor.pbobjc.m
new file mode 100644
index 00000000..b7d2e64f
--- /dev/null
+++ b/objectivec/google/protobuf/Descriptor.pbobjc.m
@@ -0,0 +1,2205 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/descriptor.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+
+#import "google/protobuf/Descriptor.pbobjc.h"
+
+#pragma mark - GPBDescriptorRoot
+
+@implementation GPBDescriptorRoot
+
+@end
+
+static GPBFileDescriptor *GPBDescriptorRoot_FileDescriptor(void) {
+ // This is called by +initialize so there is no need to worry
+ // about thread safety of the singleton.
+ static GPBFileDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ syntax:GPBFileSyntaxProto2];
+ }
+ return descriptor;
+}
+
+#pragma mark - GPBFileDescriptorSet
+
+@implementation GPBFileDescriptorSet
+
+@dynamic fileArray;
+
+typedef struct GPBFileDescriptorSet_Storage {
+ uint32_t _has_storage_[1];
+ NSMutableArray *fileArray;
+} GPBFileDescriptorSet_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "fileArray",
+ .number = GPBFileDescriptorSet_FieldNumber_FileArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBFileDescriptorSet_Storage, fileArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBFileDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFileDescriptorSet class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBFileDescriptorSet_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBFileDescriptorProto
+
+@implementation GPBFileDescriptorProto
+
+@dynamic hasName, name;
+@dynamic hasPackage, package;
+@dynamic dependencyArray;
+@dynamic publicDependencyArray;
+@dynamic weakDependencyArray;
+@dynamic messageTypeArray;
+@dynamic enumTypeArray;
+@dynamic serviceArray;
+@dynamic extensionArray;
+@dynamic hasOptions, options;
+@dynamic hasSourceCodeInfo, sourceCodeInfo;
+@dynamic hasSyntax, syntax;
+
+typedef struct GPBFileDescriptorProto_Storage {
+ uint32_t _has_storage_[1];
+ NSString *name;
+ NSString *package;
+ NSMutableArray *dependencyArray;
+ NSMutableArray *messageTypeArray;
+ NSMutableArray *enumTypeArray;
+ NSMutableArray *serviceArray;
+ NSMutableArray *extensionArray;
+ GPBFileOptions *options;
+ GPBSourceCodeInfo *sourceCodeInfo;
+ GPBInt32Array *publicDependencyArray;
+ GPBInt32Array *weakDependencyArray;
+ NSString *syntax;
+} GPBFileDescriptorProto_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "name",
+ .number = GPBFileDescriptorProto_FieldNumber_Name,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, name),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "package",
+ .number = GPBFileDescriptorProto_FieldNumber_Package,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, package),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "dependencyArray",
+ .number = GPBFileDescriptorProto_FieldNumber_DependencyArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, dependencyArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "messageTypeArray",
+ .number = GPBFileDescriptorProto_FieldNumber_MessageTypeArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, messageTypeArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "enumTypeArray",
+ .number = GPBFileDescriptorProto_FieldNumber_EnumTypeArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, enumTypeArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "serviceArray",
+ .number = GPBFileDescriptorProto_FieldNumber_ServiceArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, serviceArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBServiceDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "extensionArray",
+ .number = GPBFileDescriptorProto_FieldNumber_ExtensionArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, extensionArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "options",
+ .number = GPBFileDescriptorProto_FieldNumber_Options,
+ .hasIndex = 9,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, options),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBFileOptions),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "sourceCodeInfo",
+ .number = GPBFileDescriptorProto_FieldNumber_SourceCodeInfo,
+ .hasIndex = 10,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, sourceCodeInfo),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "publicDependencyArray",
+ .number = GPBFileDescriptorProto_FieldNumber_PublicDependencyArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, publicDependencyArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "weakDependencyArray",
+ .number = GPBFileDescriptorProto_FieldNumber_WeakDependencyArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, weakDependencyArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "syntax",
+ .number = GPBFileDescriptorProto_FieldNumber_Syntax,
+ .hasIndex = 11,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFileDescriptorProto_Storage, syntax),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFileDescriptorProto class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBFileDescriptorProto_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBDescriptorProto
+
+@implementation GPBDescriptorProto
+
+@dynamic hasName, name;
+@dynamic fieldArray;
+@dynamic extensionArray;
+@dynamic nestedTypeArray;
+@dynamic enumTypeArray;
+@dynamic extensionRangeArray;
+@dynamic oneofDeclArray;
+@dynamic hasOptions, options;
+
+typedef struct GPBDescriptorProto_Storage {
+ uint32_t _has_storage_[1];
+ NSString *name;
+ NSMutableArray *fieldArray;
+ NSMutableArray *nestedTypeArray;
+ NSMutableArray *enumTypeArray;
+ NSMutableArray *extensionRangeArray;
+ NSMutableArray *extensionArray;
+ GPBMessageOptions *options;
+ NSMutableArray *oneofDeclArray;
+} GPBDescriptorProto_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "name",
+ .number = GPBDescriptorProto_FieldNumber_Name,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBDescriptorProto_Storage, name),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "fieldArray",
+ .number = GPBDescriptorProto_FieldNumber_FieldArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBDescriptorProto_Storage, fieldArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "nestedTypeArray",
+ .number = GPBDescriptorProto_FieldNumber_NestedTypeArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBDescriptorProto_Storage, nestedTypeArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "enumTypeArray",
+ .number = GPBDescriptorProto_FieldNumber_EnumTypeArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBDescriptorProto_Storage, enumTypeArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBEnumDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "extensionRangeArray",
+ .number = GPBDescriptorProto_FieldNumber_ExtensionRangeArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBDescriptorProto_Storage, extensionRangeArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBDescriptorProto_ExtensionRange),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "extensionArray",
+ .number = GPBDescriptorProto_FieldNumber_ExtensionArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBDescriptorProto_Storage, extensionArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBFieldDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "options",
+ .number = GPBDescriptorProto_FieldNumber_Options,
+ .hasIndex = 7,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBDescriptorProto_Storage, options),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBMessageOptions),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "oneofDeclArray",
+ .number = GPBDescriptorProto_FieldNumber_OneofDeclArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBDescriptorProto_Storage, oneofDeclArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBOneofDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBDescriptorProto_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBDescriptorProto_ExtensionRange
+
+@implementation GPBDescriptorProto_ExtensionRange
+
+@dynamic hasStart, start;
+@dynamic hasEnd, end;
+
+typedef struct GPBDescriptorProto_ExtensionRange_Storage {
+ uint32_t _has_storage_[1];
+ int32_t start;
+ int32_t end;
+} GPBDescriptorProto_ExtensionRange_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "start",
+ .number = GPBDescriptorProto_ExtensionRange_FieldNumber_Start,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBDescriptorProto_ExtensionRange_Storage, start),
+ .defaultValue.valueInt32 = 0,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "end",
+ .number = GPBDescriptorProto_ExtensionRange_FieldNumber_End,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBDescriptorProto_ExtensionRange_Storage, end),
+ .defaultValue.valueInt32 = 0,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDescriptorProto_ExtensionRange class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBDescriptorProto_ExtensionRange_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBFieldDescriptorProto
+
+@implementation GPBFieldDescriptorProto
+
+@dynamic hasName, name;
+@dynamic hasNumber, number;
+@dynamic hasLabel, label;
+@dynamic hasType, type;
+@dynamic hasTypeName, typeName;
+@dynamic hasExtendee, extendee;
+@dynamic hasDefaultValue, defaultValue;
+@dynamic hasOneofIndex, oneofIndex;
+@dynamic hasOptions, options;
+
+typedef struct GPBFieldDescriptorProto_Storage {
+ uint32_t _has_storage_[1];
+ int32_t number;
+ GPBFieldDescriptorProto_Label label;
+ GPBFieldDescriptorProto_Type type;
+ int32_t oneofIndex;
+ NSString *name;
+ NSString *extendee;
+ NSString *typeName;
+ NSString *defaultValue;
+ GPBFieldOptions *options;
+} GPBFieldDescriptorProto_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "name",
+ .number = GPBFieldDescriptorProto_FieldNumber_Name,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFieldDescriptorProto_Storage, name),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "extendee",
+ .number = GPBFieldDescriptorProto_FieldNumber_Extendee,
+ .hasIndex = 5,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFieldDescriptorProto_Storage, extendee),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "number",
+ .number = GPBFieldDescriptorProto_FieldNumber_Number,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBFieldDescriptorProto_Storage, number),
+ .defaultValue.valueInt32 = 0,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "label",
+ .number = GPBFieldDescriptorProto_FieldNumber_Label,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .type = GPBTypeEnum,
+ .offset = offsetof(GPBFieldDescriptorProto_Storage, label),
+ .defaultValue.valueEnum = GPBFieldDescriptorProto_Label_LabelOptional,
+ .typeSpecific.enumDescFunc = GPBFieldDescriptorProto_Label_EnumDescriptor,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "type",
+ .number = GPBFieldDescriptorProto_FieldNumber_Type,
+ .hasIndex = 3,
+ .flags = GPBFieldOptional | GPBFieldHasEnumDescriptor,
+ .type = GPBTypeEnum,
+ .offset = offsetof(GPBFieldDescriptorProto_Storage, type),
+ .defaultValue.valueEnum = GPBFieldDescriptorProto_Type_TypeDouble,
+ .typeSpecific.enumDescFunc = GPBFieldDescriptorProto_Type_EnumDescriptor,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "typeName",
+ .number = GPBFieldDescriptorProto_FieldNumber_TypeName,
+ .hasIndex = 4,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFieldDescriptorProto_Storage, typeName),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "defaultValue",
+ .number = GPBFieldDescriptorProto_FieldNumber_DefaultValue,
+ .hasIndex = 6,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFieldDescriptorProto_Storage, defaultValue),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "options",
+ .number = GPBFieldDescriptorProto_FieldNumber_Options,
+ .hasIndex = 8,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBFieldDescriptorProto_Storage, options),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBFieldOptions),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "oneofIndex",
+ .number = GPBFieldDescriptorProto_FieldNumber_OneofIndex,
+ .hasIndex = 7,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBFieldDescriptorProto_Storage, oneofIndex),
+ .defaultValue.valueInt32 = 0,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ static GPBMessageEnumDescription enums[] = {
+ { .enumDescriptorFunc = GPBFieldDescriptorProto_Type_EnumDescriptor },
+ { .enumDescriptorFunc = GPBFieldDescriptorProto_Label_EnumDescriptor },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFieldDescriptorProto class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:enums
+ enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBFieldDescriptorProto_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - Enum GPBFieldDescriptorProto_Type
+
+GPBEnumDescriptor *GPBFieldDescriptorProto_Type_EnumDescriptor(void) {
+ static GPBEnumDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageEnumValueDescription values[] = {
+ { .name = "TypeDouble", .number = GPBFieldDescriptorProto_Type_TypeDouble },
+ { .name = "TypeFloat", .number = GPBFieldDescriptorProto_Type_TypeFloat },
+ { .name = "TypeInt64", .number = GPBFieldDescriptorProto_Type_TypeInt64 },
+ { .name = "TypeUint64", .number = GPBFieldDescriptorProto_Type_TypeUint64 },
+ { .name = "TypeInt32", .number = GPBFieldDescriptorProto_Type_TypeInt32 },
+ { .name = "TypeFixed64", .number = GPBFieldDescriptorProto_Type_TypeFixed64 },
+ { .name = "TypeFixed32", .number = GPBFieldDescriptorProto_Type_TypeFixed32 },
+ { .name = "TypeBool", .number = GPBFieldDescriptorProto_Type_TypeBool },
+ { .name = "TypeString", .number = GPBFieldDescriptorProto_Type_TypeString },
+ { .name = "TypeGroup", .number = GPBFieldDescriptorProto_Type_TypeGroup },
+ { .name = "TypeMessage", .number = GPBFieldDescriptorProto_Type_TypeMessage },
+ { .name = "TypeBytes", .number = GPBFieldDescriptorProto_Type_TypeBytes },
+ { .name = "TypeUint32", .number = GPBFieldDescriptorProto_Type_TypeUint32 },
+ { .name = "TypeEnum", .number = GPBFieldDescriptorProto_Type_TypeEnum },
+ { .name = "TypeSfixed32", .number = GPBFieldDescriptorProto_Type_TypeSfixed32 },
+ { .name = "TypeSfixed64", .number = GPBFieldDescriptorProto_Type_TypeSfixed64 },
+ { .name = "TypeSint32", .number = GPBFieldDescriptorProto_Type_TypeSint32 },
+ { .name = "TypeSint64", .number = GPBFieldDescriptorProto_Type_TypeSint64 },
+ };
+ descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBFieldDescriptorProto_Type)
+ values:values
+ valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)
+ enumVerifier:GPBFieldDescriptorProto_Type_IsValidValue];
+ }
+ return descriptor;
+}
+
+BOOL GPBFieldDescriptorProto_Type_IsValidValue(int32_t value__) {
+ switch (value__) {
+ case GPBFieldDescriptorProto_Type_TypeDouble:
+ case GPBFieldDescriptorProto_Type_TypeFloat:
+ case GPBFieldDescriptorProto_Type_TypeInt64:
+ case GPBFieldDescriptorProto_Type_TypeUint64:
+ case GPBFieldDescriptorProto_Type_TypeInt32:
+ case GPBFieldDescriptorProto_Type_TypeFixed64:
+ case GPBFieldDescriptorProto_Type_TypeFixed32:
+ case GPBFieldDescriptorProto_Type_TypeBool:
+ case GPBFieldDescriptorProto_Type_TypeString:
+ case GPBFieldDescriptorProto_Type_TypeGroup:
+ case GPBFieldDescriptorProto_Type_TypeMessage:
+ case GPBFieldDescriptorProto_Type_TypeBytes:
+ case GPBFieldDescriptorProto_Type_TypeUint32:
+ case GPBFieldDescriptorProto_Type_TypeEnum:
+ case GPBFieldDescriptorProto_Type_TypeSfixed32:
+ case GPBFieldDescriptorProto_Type_TypeSfixed64:
+ case GPBFieldDescriptorProto_Type_TypeSint32:
+ case GPBFieldDescriptorProto_Type_TypeSint64:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+#pragma mark - Enum GPBFieldDescriptorProto_Label
+
+GPBEnumDescriptor *GPBFieldDescriptorProto_Label_EnumDescriptor(void) {
+ static GPBEnumDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageEnumValueDescription values[] = {
+ { .name = "LabelOptional", .number = GPBFieldDescriptorProto_Label_LabelOptional },
+ { .name = "LabelRequired", .number = GPBFieldDescriptorProto_Label_LabelRequired },
+ { .name = "LabelRepeated", .number = GPBFieldDescriptorProto_Label_LabelRepeated },
+ };
+ descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBFieldDescriptorProto_Label)
+ values:values
+ valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)
+ enumVerifier:GPBFieldDescriptorProto_Label_IsValidValue];
+ }
+ return descriptor;
+}
+
+BOOL GPBFieldDescriptorProto_Label_IsValidValue(int32_t value__) {
+ switch (value__) {
+ case GPBFieldDescriptorProto_Label_LabelOptional:
+ case GPBFieldDescriptorProto_Label_LabelRequired:
+ case GPBFieldDescriptorProto_Label_LabelRepeated:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+#pragma mark - GPBOneofDescriptorProto
+
+@implementation GPBOneofDescriptorProto
+
+@dynamic hasName, name;
+
+typedef struct GPBOneofDescriptorProto_Storage {
+ uint32_t _has_storage_[1];
+ NSString *name;
+} GPBOneofDescriptorProto_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "name",
+ .number = GPBOneofDescriptorProto_FieldNumber_Name,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBOneofDescriptorProto_Storage, name),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBOneofDescriptorProto class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBOneofDescriptorProto_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBEnumDescriptorProto
+
+@implementation GPBEnumDescriptorProto
+
+@dynamic hasName, name;
+@dynamic valueArray;
+@dynamic hasOptions, options;
+
+typedef struct GPBEnumDescriptorProto_Storage {
+ uint32_t _has_storage_[1];
+ NSString *name;
+ NSMutableArray *valueArray;
+ GPBEnumOptions *options;
+} GPBEnumDescriptorProto_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "name",
+ .number = GPBEnumDescriptorProto_FieldNumber_Name,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBEnumDescriptorProto_Storage, name),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "valueArray",
+ .number = GPBEnumDescriptorProto_FieldNumber_ValueArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBEnumDescriptorProto_Storage, valueArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBEnumValueDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "options",
+ .number = GPBEnumDescriptorProto_FieldNumber_Options,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBEnumDescriptorProto_Storage, options),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBEnumOptions),
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumDescriptorProto class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBEnumDescriptorProto_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBEnumValueDescriptorProto
+
+@implementation GPBEnumValueDescriptorProto
+
+@dynamic hasName, name;
+@dynamic hasNumber, number;
+@dynamic hasOptions, options;
+
+typedef struct GPBEnumValueDescriptorProto_Storage {
+ uint32_t _has_storage_[1];
+ int32_t number;
+ NSString *name;
+ GPBEnumValueOptions *options;
+} GPBEnumValueDescriptorProto_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "name",
+ .number = GPBEnumValueDescriptorProto_FieldNumber_Name,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBEnumValueDescriptorProto_Storage, name),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "number",
+ .number = GPBEnumValueDescriptorProto_FieldNumber_Number,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBEnumValueDescriptorProto_Storage, number),
+ .defaultValue.valueInt32 = 0,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "options",
+ .number = GPBEnumValueDescriptorProto_FieldNumber_Options,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBEnumValueDescriptorProto_Storage, options),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBEnumValueOptions),
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumValueDescriptorProto class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBEnumValueDescriptorProto_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBServiceDescriptorProto
+
+@implementation GPBServiceDescriptorProto
+
+@dynamic hasName, name;
+@dynamic methodArray;
+@dynamic hasOptions, options;
+
+typedef struct GPBServiceDescriptorProto_Storage {
+ uint32_t _has_storage_[1];
+ NSString *name;
+ NSMutableArray *methodArray;
+ GPBServiceOptions *options;
+} GPBServiceDescriptorProto_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "name",
+ .number = GPBServiceDescriptorProto_FieldNumber_Name,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBServiceDescriptorProto_Storage, name),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "methodArray",
+ .number = GPBServiceDescriptorProto_FieldNumber_MethodArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBServiceDescriptorProto_Storage, methodArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBMethodDescriptorProto),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "options",
+ .number = GPBServiceDescriptorProto_FieldNumber_Options,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBServiceDescriptorProto_Storage, options),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBServiceOptions),
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBServiceDescriptorProto class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBServiceDescriptorProto_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBMethodDescriptorProto
+
+@implementation GPBMethodDescriptorProto
+
+@dynamic hasName, name;
+@dynamic hasInputType, inputType;
+@dynamic hasOutputType, outputType;
+@dynamic hasOptions, options;
+@dynamic hasClientStreaming, clientStreaming;
+@dynamic hasServerStreaming, serverStreaming;
+
+typedef struct GPBMethodDescriptorProto_Storage {
+ uint32_t _has_storage_[1];
+ BOOL clientStreaming;
+ BOOL serverStreaming;
+ NSString *name;
+ NSString *inputType;
+ NSString *outputType;
+ GPBMethodOptions *options;
+} GPBMethodDescriptorProto_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "name",
+ .number = GPBMethodDescriptorProto_FieldNumber_Name,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBMethodDescriptorProto_Storage, name),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "inputType",
+ .number = GPBMethodDescriptorProto_FieldNumber_InputType,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBMethodDescriptorProto_Storage, inputType),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "outputType",
+ .number = GPBMethodDescriptorProto_FieldNumber_OutputType,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBMethodDescriptorProto_Storage, outputType),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "options",
+ .number = GPBMethodDescriptorProto_FieldNumber_Options,
+ .hasIndex = 3,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBMethodDescriptorProto_Storage, options),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBMethodOptions),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "clientStreaming",
+ .number = GPBMethodDescriptorProto_FieldNumber_ClientStreaming,
+ .hasIndex = 4,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBMethodDescriptorProto_Storage, clientStreaming),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "serverStreaming",
+ .number = GPBMethodDescriptorProto_FieldNumber_ServerStreaming,
+ .hasIndex = 5,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBMethodDescriptorProto_Storage, serverStreaming),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMethodDescriptorProto class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBMethodDescriptorProto_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBFileOptions
+
+@implementation GPBFileOptions
+
+@dynamic hasJavaPackage, javaPackage;
+@dynamic hasJavaOuterClassname, javaOuterClassname;
+@dynamic hasJavaMultipleFiles, javaMultipleFiles;
+@dynamic hasJavaGenerateEqualsAndHash, javaGenerateEqualsAndHash;
+@dynamic hasJavaStringCheckUtf8, javaStringCheckUtf8;
+@dynamic hasOptimizeFor, optimizeFor;
+@dynamic hasGoPackage, goPackage;
+@dynamic hasCcGenericServices, ccGenericServices;
+@dynamic hasJavaGenericServices, javaGenericServices;
+@dynamic hasPyGenericServices, pyGenericServices;
+@dynamic hasDeprecated, deprecated;
+@dynamic hasCcEnableArenas, ccEnableArenas;
+@dynamic hasObjcClassPrefix, objcClassPrefix;
+@dynamic uninterpretedOptionArray;
+
+typedef struct GPBFileOptions_Storage {
+ uint32_t _has_storage_[1];
+ BOOL javaMultipleFiles;
+ BOOL ccGenericServices;
+ BOOL javaGenericServices;
+ BOOL pyGenericServices;
+ BOOL javaGenerateEqualsAndHash;
+ BOOL deprecated;
+ BOOL javaStringCheckUtf8;
+ BOOL ccEnableArenas;
+ GPBFileOptions_OptimizeMode optimizeFor;
+ NSString *javaPackage;
+ NSString *javaOuterClassname;
+ NSString *goPackage;
+ NSString *objcClassPrefix;
+ NSMutableArray *uninterpretedOptionArray;
+} GPBFileOptions_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "javaPackage",
+ .number = GPBFileOptions_FieldNumber_JavaPackage,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFileOptions_Storage, javaPackage),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "javaOuterClassname",
+ .number = GPBFileOptions_FieldNumber_JavaOuterClassname,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFileOptions_Storage, javaOuterClassname),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "optimizeFor",
+ .number = GPBFileOptions_FieldNumber_OptimizeFor,
+ .hasIndex = 5,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor,
+ .type = GPBTypeEnum,
+ .offset = offsetof(GPBFileOptions_Storage, optimizeFor),
+ .defaultValue.valueEnum = GPBFileOptions_OptimizeMode_Speed,
+ .typeSpecific.enumDescFunc = GPBFileOptions_OptimizeMode_EnumDescriptor,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "javaMultipleFiles",
+ .number = GPBFileOptions_FieldNumber_JavaMultipleFiles,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFileOptions_Storage, javaMultipleFiles),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "goPackage",
+ .number = GPBFileOptions_FieldNumber_GoPackage,
+ .hasIndex = 6,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFileOptions_Storage, goPackage),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "ccGenericServices",
+ .number = GPBFileOptions_FieldNumber_CcGenericServices,
+ .hasIndex = 7,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFileOptions_Storage, ccGenericServices),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "javaGenericServices",
+ .number = GPBFileOptions_FieldNumber_JavaGenericServices,
+ .hasIndex = 8,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFileOptions_Storage, javaGenericServices),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "pyGenericServices",
+ .number = GPBFileOptions_FieldNumber_PyGenericServices,
+ .hasIndex = 9,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFileOptions_Storage, pyGenericServices),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "javaGenerateEqualsAndHash",
+ .number = GPBFileOptions_FieldNumber_JavaGenerateEqualsAndHash,
+ .hasIndex = 3,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFileOptions_Storage, javaGenerateEqualsAndHash),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "deprecated",
+ .number = GPBFileOptions_FieldNumber_Deprecated,
+ .hasIndex = 10,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFileOptions_Storage, deprecated),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "javaStringCheckUtf8",
+ .number = GPBFileOptions_FieldNumber_JavaStringCheckUtf8,
+ .hasIndex = 4,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFileOptions_Storage, javaStringCheckUtf8),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "ccEnableArenas",
+ .number = GPBFileOptions_FieldNumber_CcEnableArenas,
+ .hasIndex = 11,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFileOptions_Storage, ccEnableArenas),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "objcClassPrefix",
+ .number = GPBFileOptions_FieldNumber_ObjcClassPrefix,
+ .hasIndex = 12,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBFileOptions_Storage, objcClassPrefix),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "uninterpretedOptionArray",
+ .number = GPBFileOptions_FieldNumber_UninterpretedOptionArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBFileOptions_Storage, uninterpretedOptionArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+ .fieldOptions = NULL,
+ },
+ };
+ static GPBMessageEnumDescription enums[] = {
+ { .enumDescriptorFunc = GPBFileOptions_OptimizeMode_EnumDescriptor },
+ };
+ static GPBExtensionRange ranges[] = {
+ { .start = 1000, .end = 536870912 },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFileOptions class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:enums
+ enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
+ ranges:ranges
+ rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+ storageSize:sizeof(GPBFileOptions_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - Enum GPBFileOptions_OptimizeMode
+
+GPBEnumDescriptor *GPBFileOptions_OptimizeMode_EnumDescriptor(void) {
+ static GPBEnumDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageEnumValueDescription values[] = {
+ { .name = "Speed", .number = GPBFileOptions_OptimizeMode_Speed },
+ { .name = "CodeSize", .number = GPBFileOptions_OptimizeMode_CodeSize },
+ { .name = "LiteRuntime", .number = GPBFileOptions_OptimizeMode_LiteRuntime },
+ };
+ descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBFileOptions_OptimizeMode)
+ values:values
+ valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)
+ enumVerifier:GPBFileOptions_OptimizeMode_IsValidValue];
+ }
+ return descriptor;
+}
+
+BOOL GPBFileOptions_OptimizeMode_IsValidValue(int32_t value__) {
+ switch (value__) {
+ case GPBFileOptions_OptimizeMode_Speed:
+ case GPBFileOptions_OptimizeMode_CodeSize:
+ case GPBFileOptions_OptimizeMode_LiteRuntime:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+#pragma mark - GPBMessageOptions
+
+@implementation GPBMessageOptions
+
+@dynamic hasMessageSetWireFormat, messageSetWireFormat;
+@dynamic hasNoStandardDescriptorAccessor, noStandardDescriptorAccessor;
+@dynamic hasDeprecated, deprecated;
+@dynamic hasMapEntry, mapEntry;
+@dynamic uninterpretedOptionArray;
+
+typedef struct GPBMessageOptions_Storage {
+ uint32_t _has_storage_[1];
+ BOOL messageSetWireFormat;
+ BOOL noStandardDescriptorAccessor;
+ BOOL deprecated;
+ BOOL mapEntry;
+ NSMutableArray *uninterpretedOptionArray;
+} GPBMessageOptions_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "messageSetWireFormat",
+ .number = GPBMessageOptions_FieldNumber_MessageSetWireFormat,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBMessageOptions_Storage, messageSetWireFormat),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "noStandardDescriptorAccessor",
+ .number = GPBMessageOptions_FieldNumber_NoStandardDescriptorAccessor,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBMessageOptions_Storage, noStandardDescriptorAccessor),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "deprecated",
+ .number = GPBMessageOptions_FieldNumber_Deprecated,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBMessageOptions_Storage, deprecated),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "mapEntry",
+ .number = GPBMessageOptions_FieldNumber_MapEntry,
+ .hasIndex = 3,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBMessageOptions_Storage, mapEntry),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "uninterpretedOptionArray",
+ .number = GPBMessageOptions_FieldNumber_UninterpretedOptionArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBMessageOptions_Storage, uninterpretedOptionArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+ .fieldOptions = NULL,
+ },
+ };
+ static GPBExtensionRange ranges[] = {
+ { .start = 1000, .end = 536870912 },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessageOptions class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:ranges
+ rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+ storageSize:sizeof(GPBMessageOptions_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBFieldOptions
+
+@implementation GPBFieldOptions
+
+@dynamic hasCtype, ctype;
+@dynamic hasPacked, packed;
+@dynamic hasLazy, lazy;
+@dynamic hasDeprecated, deprecated;
+@dynamic hasWeak, weak;
+@dynamic uninterpretedOptionArray;
+
+typedef struct GPBFieldOptions_Storage {
+ uint32_t _has_storage_[1];
+ BOOL packed;
+ BOOL deprecated;
+ BOOL lazy;
+ BOOL weak;
+ GPBFieldOptions_CType ctype;
+ NSMutableArray *uninterpretedOptionArray;
+} GPBFieldOptions_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "ctype",
+ .number = GPBFieldOptions_FieldNumber_Ctype,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue | GPBFieldHasEnumDescriptor,
+ .type = GPBTypeEnum,
+ .offset = offsetof(GPBFieldOptions_Storage, ctype),
+ .defaultValue.valueEnum = GPBFieldOptions_CType_String,
+ .typeSpecific.enumDescFunc = GPBFieldOptions_CType_EnumDescriptor,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "packed",
+ .number = GPBFieldOptions_FieldNumber_Packed,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFieldOptions_Storage, packed),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "deprecated",
+ .number = GPBFieldOptions_FieldNumber_Deprecated,
+ .hasIndex = 3,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFieldOptions_Storage, deprecated),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "lazy",
+ .number = GPBFieldOptions_FieldNumber_Lazy,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFieldOptions_Storage, lazy),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "weak",
+ .number = GPBFieldOptions_FieldNumber_Weak,
+ .hasIndex = 4,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBFieldOptions_Storage, weak),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "uninterpretedOptionArray",
+ .number = GPBFieldOptions_FieldNumber_UninterpretedOptionArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBFieldOptions_Storage, uninterpretedOptionArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+ .fieldOptions = NULL,
+ },
+ };
+ static GPBMessageEnumDescription enums[] = {
+ { .enumDescriptorFunc = GPBFieldOptions_CType_EnumDescriptor },
+ };
+ static GPBExtensionRange ranges[] = {
+ { .start = 1000, .end = 536870912 },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBFieldOptions class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:enums
+ enumCount:sizeof(enums) / sizeof(GPBMessageEnumDescription)
+ ranges:ranges
+ rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+ storageSize:sizeof(GPBFieldOptions_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - Enum GPBFieldOptions_CType
+
+GPBEnumDescriptor *GPBFieldOptions_CType_EnumDescriptor(void) {
+ static GPBEnumDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageEnumValueDescription values[] = {
+ { .name = "String", .number = GPBFieldOptions_CType_String },
+ { .name = "Cord", .number = GPBFieldOptions_CType_Cord },
+ { .name = "StringPiece", .number = GPBFieldOptions_CType_StringPiece },
+ };
+ descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBFieldOptions_CType)
+ values:values
+ valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)
+ enumVerifier:GPBFieldOptions_CType_IsValidValue];
+ }
+ return descriptor;
+}
+
+BOOL GPBFieldOptions_CType_IsValidValue(int32_t value__) {
+ switch (value__) {
+ case GPBFieldOptions_CType_String:
+ case GPBFieldOptions_CType_Cord:
+ case GPBFieldOptions_CType_StringPiece:
+ return YES;
+ default:
+ return NO;
+ }
+}
+
+#pragma mark - GPBEnumOptions
+
+@implementation GPBEnumOptions
+
+@dynamic hasAllowAlias, allowAlias;
+@dynamic hasDeprecated, deprecated;
+@dynamic uninterpretedOptionArray;
+
+typedef struct GPBEnumOptions_Storage {
+ uint32_t _has_storage_[1];
+ BOOL allowAlias;
+ BOOL deprecated;
+ NSMutableArray *uninterpretedOptionArray;
+} GPBEnumOptions_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "allowAlias",
+ .number = GPBEnumOptions_FieldNumber_AllowAlias,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBEnumOptions_Storage, allowAlias),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "deprecated",
+ .number = GPBEnumOptions_FieldNumber_Deprecated,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBEnumOptions_Storage, deprecated),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "uninterpretedOptionArray",
+ .number = GPBEnumOptions_FieldNumber_UninterpretedOptionArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBEnumOptions_Storage, uninterpretedOptionArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+ .fieldOptions = NULL,
+ },
+ };
+ static GPBExtensionRange ranges[] = {
+ { .start = 1000, .end = 536870912 },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumOptions class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:ranges
+ rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+ storageSize:sizeof(GPBEnumOptions_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBEnumValueOptions
+
+@implementation GPBEnumValueOptions
+
+@dynamic hasDeprecated, deprecated;
+@dynamic uninterpretedOptionArray;
+
+typedef struct GPBEnumValueOptions_Storage {
+ uint32_t _has_storage_[1];
+ BOOL deprecated;
+ NSMutableArray *uninterpretedOptionArray;
+} GPBEnumValueOptions_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "deprecated",
+ .number = GPBEnumValueOptions_FieldNumber_Deprecated,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBEnumValueOptions_Storage, deprecated),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "uninterpretedOptionArray",
+ .number = GPBEnumValueOptions_FieldNumber_UninterpretedOptionArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBEnumValueOptions_Storage, uninterpretedOptionArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+ .fieldOptions = NULL,
+ },
+ };
+ static GPBExtensionRange ranges[] = {
+ { .start = 1000, .end = 536870912 },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBEnumValueOptions class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:ranges
+ rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+ storageSize:sizeof(GPBEnumValueOptions_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBServiceOptions
+
+@implementation GPBServiceOptions
+
+@dynamic hasDeprecated, deprecated;
+@dynamic uninterpretedOptionArray;
+
+typedef struct GPBServiceOptions_Storage {
+ uint32_t _has_storage_[1];
+ BOOL deprecated;
+ NSMutableArray *uninterpretedOptionArray;
+} GPBServiceOptions_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "deprecated",
+ .number = GPBServiceOptions_FieldNumber_Deprecated,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBServiceOptions_Storage, deprecated),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "uninterpretedOptionArray",
+ .number = GPBServiceOptions_FieldNumber_UninterpretedOptionArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBServiceOptions_Storage, uninterpretedOptionArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+ .fieldOptions = NULL,
+ },
+ };
+ static GPBExtensionRange ranges[] = {
+ { .start = 1000, .end = 536870912 },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBServiceOptions class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:ranges
+ rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+ storageSize:sizeof(GPBServiceOptions_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBMethodOptions
+
+@implementation GPBMethodOptions
+
+@dynamic hasDeprecated, deprecated;
+@dynamic uninterpretedOptionArray;
+
+typedef struct GPBMethodOptions_Storage {
+ uint32_t _has_storage_[1];
+ BOOL deprecated;
+ NSMutableArray *uninterpretedOptionArray;
+} GPBMethodOptions_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "deprecated",
+ .number = GPBMethodOptions_FieldNumber_Deprecated,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional | GPBFieldHasDefaultValue,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBMethodOptions_Storage, deprecated),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "uninterpretedOptionArray",
+ .number = GPBMethodOptions_FieldNumber_UninterpretedOptionArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBMethodOptions_Storage, uninterpretedOptionArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption),
+ .fieldOptions = NULL,
+ },
+ };
+ static GPBExtensionRange ranges[] = {
+ { .start = 1000, .end = 536870912 },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMethodOptions class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:ranges
+ rangeCount:sizeof(ranges) / sizeof(GPBExtensionRange)
+ storageSize:sizeof(GPBMethodOptions_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBUninterpretedOption
+
+@implementation GPBUninterpretedOption
+
+@dynamic nameArray;
+@dynamic hasIdentifierValue, identifierValue;
+@dynamic hasPositiveIntValue, positiveIntValue;
+@dynamic hasNegativeIntValue, negativeIntValue;
+@dynamic hasDoubleValue, doubleValue;
+@dynamic hasStringValue, stringValue;
+@dynamic hasAggregateValue, aggregateValue;
+
+typedef struct GPBUninterpretedOption_Storage {
+ uint32_t _has_storage_[1];
+ NSMutableArray *nameArray;
+ NSString *identifierValue;
+ NSData *stringValue;
+ NSString *aggregateValue;
+ uint64_t positiveIntValue;
+ int64_t negativeIntValue;
+ double doubleValue;
+} GPBUninterpretedOption_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "nameArray",
+ .number = GPBUninterpretedOption_FieldNumber_NameArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBUninterpretedOption_Storage, nameArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBUninterpretedOption_NamePart),
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "identifierValue",
+ .number = GPBUninterpretedOption_FieldNumber_IdentifierValue,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBUninterpretedOption_Storage, identifierValue),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "positiveIntValue",
+ .number = GPBUninterpretedOption_FieldNumber_PositiveIntValue,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeUInt64,
+ .offset = offsetof(GPBUninterpretedOption_Storage, positiveIntValue),
+ .defaultValue.valueUInt64 = 0ULL,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "negativeIntValue",
+ .number = GPBUninterpretedOption_FieldNumber_NegativeIntValue,
+ .hasIndex = 3,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeInt64,
+ .offset = offsetof(GPBUninterpretedOption_Storage, negativeIntValue),
+ .defaultValue.valueInt64 = 0LL,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "doubleValue",
+ .number = GPBUninterpretedOption_FieldNumber_DoubleValue,
+ .hasIndex = 4,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeDouble,
+ .offset = offsetof(GPBUninterpretedOption_Storage, doubleValue),
+ .defaultValue.valueDouble = 0,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "stringValue",
+ .number = GPBUninterpretedOption_FieldNumber_StringValue,
+ .hasIndex = 5,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeData,
+ .offset = offsetof(GPBUninterpretedOption_Storage, stringValue),
+ .defaultValue.valueData = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "aggregateValue",
+ .number = GPBUninterpretedOption_FieldNumber_AggregateValue,
+ .hasIndex = 6,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBUninterpretedOption_Storage, aggregateValue),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUninterpretedOption class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBUninterpretedOption_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBUninterpretedOption_NamePart
+
+@implementation GPBUninterpretedOption_NamePart
+
+@dynamic hasNamePart, namePart;
+@dynamic hasIsExtension, isExtension;
+
+typedef struct GPBUninterpretedOption_NamePart_Storage {
+ uint32_t _has_storage_[1];
+ BOOL isExtension;
+ NSString *namePart;
+} GPBUninterpretedOption_NamePart_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "namePart",
+ .number = GPBUninterpretedOption_NamePart_FieldNumber_NamePart,
+ .hasIndex = 0,
+ .flags = GPBFieldRequired,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBUninterpretedOption_NamePart_Storage, namePart),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "isExtension",
+ .number = GPBUninterpretedOption_NamePart_FieldNumber_IsExtension,
+ .hasIndex = 1,
+ .flags = GPBFieldRequired,
+ .type = GPBTypeBool,
+ .offset = offsetof(GPBUninterpretedOption_NamePart_Storage, isExtension),
+ .defaultValue.valueBool = NO,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBUninterpretedOption_NamePart class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBUninterpretedOption_NamePart_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBSourceCodeInfo
+
+@implementation GPBSourceCodeInfo
+
+@dynamic locationArray;
+
+typedef struct GPBSourceCodeInfo_Storage {
+ uint32_t _has_storage_[1];
+ NSMutableArray *locationArray;
+} GPBSourceCodeInfo_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "locationArray",
+ .number = GPBSourceCodeInfo_FieldNumber_LocationArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeMessage,
+ .offset = offsetof(GPBSourceCodeInfo_Storage, locationArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = GPBStringifySymbol(GPBSourceCodeInfo_Location),
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBSourceCodeInfo class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBSourceCodeInfo_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
+#pragma mark - GPBSourceCodeInfo_Location
+
+@implementation GPBSourceCodeInfo_Location
+
+@dynamic pathArray;
+@dynamic spanArray;
+@dynamic hasLeadingComments, leadingComments;
+@dynamic hasTrailingComments, trailingComments;
+@dynamic leadingDetachedCommentsArray;
+
+typedef struct GPBSourceCodeInfo_Location_Storage {
+ uint32_t _has_storage_[1];
+ GPBInt32Array *pathArray;
+ GPBInt32Array *spanArray;
+ NSString *leadingComments;
+ NSString *trailingComments;
+ NSMutableArray *leadingDetachedCommentsArray;
+} GPBSourceCodeInfo_Location_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "pathArray",
+ .number = GPBSourceCodeInfo_Location_FieldNumber_PathArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated | GPBFieldPacked,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBSourceCodeInfo_Location_Storage, pathArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = NULL,
+ #if GPBOBJC_INCLUDE_FIELD_OPTIONS
+ .fieldOptions = "\000\000\000\002\020\001",
+ #else
+ .fieldOptions = NULL,
+ #endif // GPBOBJC_INCLUDE_FIELD_OPTIONS
+ },
+ {
+ .name = "spanArray",
+ .number = GPBSourceCodeInfo_Location_FieldNumber_SpanArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated | GPBFieldPacked,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBSourceCodeInfo_Location_Storage, spanArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = NULL,
+ #if GPBOBJC_INCLUDE_FIELD_OPTIONS
+ .fieldOptions = "\000\000\000\002\020\001",
+ #else
+ .fieldOptions = NULL,
+ #endif // GPBOBJC_INCLUDE_FIELD_OPTIONS
+ },
+ {
+ .name = "leadingComments",
+ .number = GPBSourceCodeInfo_Location_FieldNumber_LeadingComments,
+ .hasIndex = 2,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBSourceCodeInfo_Location_Storage, leadingComments),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "trailingComments",
+ .number = GPBSourceCodeInfo_Location_FieldNumber_TrailingComments,
+ .hasIndex = 3,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBSourceCodeInfo_Location_Storage, trailingComments),
+ .defaultValue.valueString = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "leadingDetachedCommentsArray",
+ .number = GPBSourceCodeInfo_Location_FieldNumber_LeadingDetachedCommentsArray,
+ .hasIndex = GPBNoHasBit,
+ .flags = GPBFieldRepeated,
+ .type = GPBTypeString,
+ .offset = offsetof(GPBSourceCodeInfo_Location_Storage, leadingDetachedCommentsArray),
+ .defaultValue.valueMessage = nil,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBSourceCodeInfo_Location class]
+ rootClass:[GPBDescriptorRoot class]
+ file:GPBDescriptorRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBSourceCodeInfo_Location_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
diff --git a/objectivec/google/protobuf/Duration.pbobjc.h b/objectivec/google/protobuf/Duration.pbobjc.h
new file mode 100644
index 00000000..c452d0bb
--- /dev/null
+++ b/objectivec/google/protobuf/Duration.pbobjc.h
@@ -0,0 +1,83 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/duration.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000
+#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources.
+#endif
+
+CF_EXTERN_C_BEGIN
+
+@class GPBDuration;
+
+
+#pragma mark - GPBDurationRoot
+
+@interface GPBDurationRoot : GPBRootObject
+@end
+
+#pragma mark - GPBDuration
+
+typedef GPB_ENUM(GPBDuration_FieldNumber) {
+ GPBDuration_FieldNumber_Seconds = 1,
+ GPBDuration_FieldNumber_Nanos = 2,
+};
+
+// A Duration represents a signed, fixed-length span of time represented
+// as a count of seconds and fractions of seconds at nanosecond
+// resolution. It is independent of any calendar and concepts like "day"
+// or "month". It is related to Timestamp in that the difference between
+// two Timestamp values is a Duration and it can be added or subtracted
+// from a Timestamp. Range is approximately +-10,000 years.
+//
+// Example 1: Compute Duration from two Timestamps in pseudo code.
+//
+// Timestamp start = ...;
+// Timestamp end = ...;
+// Duration duration = ...;
+//
+// duration.seconds = end.seconds - start.seconds;
+// duration.nanos = end.nanos - start.nanos;
+//
+// if (duration.seconds < 0 && duration.nanos > 0) {
+// duration.seconds += 1;
+// duration.nanos -= 1000000000;
+// } else if (durations.seconds > 0 && duration.nanos < 0) {
+// duration.seconds -= 1;
+// duration.nanos += 1000000000;
+// }
+//
+// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
+//
+// Timestamp start = ...;
+// Duration duration = ...;
+// Timestamp end = ...;
+//
+// end.seconds = start.seconds + duration.seconds;
+// end.nanos = start.nanos + duration.nanos;
+//
+// if (end.nanos < 0) {
+// end.seconds -= 1;
+// end.nanos += 1000000000;
+// } else if (end.nanos >= 1000000000) {
+// end.seconds += 1;
+// end.nanos -= 1000000000;
+// }
+@interface GPBDuration : GPBMessage
+
+// Signed seconds of the span of time. Must be from -315,576,000,000
+// to +315,576,000,000 inclusive.
+@property(nonatomic, readwrite) int64_t seconds;
+
+// Signed fractions of a second at nanosecond resolution of the span
+// of time. Durations less than one second are represented with a 0
+// `seconds` field and a positive or negative `nanos` field. For durations
+// of one second or more, a non-zero value for the `nanos` field must be
+// of the same sign as the `seconds` field. Must be from -999,999,999
+// to +999,999,999 inclusive.
+@property(nonatomic, readwrite) int32_t nanos;
+
+@end
+
+CF_EXTERN_C_END
diff --git a/objectivec/google/protobuf/Duration.pbobjc.m b/objectivec/google/protobuf/Duration.pbobjc.m
new file mode 100644
index 00000000..cf0a3064
--- /dev/null
+++ b/objectivec/google/protobuf/Duration.pbobjc.m
@@ -0,0 +1,85 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/duration.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+
+#import "google/protobuf/Duration.pbobjc.h"
+
+#pragma mark - GPBDurationRoot
+
+@implementation GPBDurationRoot
+
+@end
+
+static GPBFileDescriptor *GPBDurationRoot_FileDescriptor(void) {
+ // This is called by +initialize so there is no need to worry
+ // about thread safety of the singleton.
+ static GPBFileDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ syntax:GPBFileSyntaxProto3];
+ }
+ return descriptor;
+}
+
+#pragma mark - GPBDuration
+
+@implementation GPBDuration
+
+@dynamic seconds;
+@dynamic nanos;
+
+typedef struct GPBDuration_Storage {
+ uint32_t _has_storage_[1];
+ int32_t nanos;
+ int64_t seconds;
+} GPBDuration_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "seconds",
+ .number = GPBDuration_FieldNumber_Seconds,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeInt64,
+ .offset = offsetof(GPBDuration_Storage, seconds),
+ .defaultValue.valueInt64 = 0LL,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "nanos",
+ .number = GPBDuration_FieldNumber_Nanos,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBDuration_Storage, nanos),
+ .defaultValue.valueInt32 = 0,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBDuration class]
+ rootClass:[GPBDurationRoot class]
+ file:GPBDurationRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBDuration_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.h b/objectivec/google/protobuf/Timestamp.pbobjc.h
new file mode 100644
index 00000000..c9fc9175
--- /dev/null
+++ b/objectivec/google/protobuf/Timestamp.pbobjc.h
@@ -0,0 +1,94 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/timestamp.proto
+
+#import "GPBProtocolBuffers.h"
+
+#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != 30000
+#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources.
+#endif
+
+CF_EXTERN_C_BEGIN
+
+@class GPBTimestamp;
+
+
+#pragma mark - GPBTimestampRoot
+
+@interface GPBTimestampRoot : GPBRootObject
+@end
+
+#pragma mark - GPBTimestamp
+
+typedef GPB_ENUM(GPBTimestamp_FieldNumber) {
+ GPBTimestamp_FieldNumber_Seconds = 1,
+ GPBTimestamp_FieldNumber_Nanos = 2,
+};
+
+// A Timestamp represents a point in time independent of any time zone
+// or calendar, represented as seconds and fractions of seconds at
+// nanosecond resolution in UTC Epoch time. It is encoded using the
+// Proleptic Gregorian Calendar which extends the Gregorian calendar
+// backwards to year one. It is encoded assuming all minutes are 60
+// seconds long, i.e. leap seconds are "smeared" so that no leap second
+// table is needed for interpretation. Range is from
+// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
+// By restricting to that range, we ensure that we can convert to
+// and from RFC 3339 date strings.
+// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
+//
+// Example 1: Compute Timestamp from POSIX `time()`.
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(time(NULL));
+// timestamp.set_nanos(0);
+//
+// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
+//
+// struct timeval tv;
+// gettimeofday(&tv, NULL);
+//
+// Timestamp timestamp;
+// timestamp.set_seconds(tv.tv_sec);
+// timestamp.set_nanos(tv.tv_usec * 1000);
+//
+// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+//
+// FILETIME ft;
+// GetSystemTimeAsFileTime(&ft);
+// UINT64 ticks = (((UINT64)ft.dwHighDateTime) << 32) | ft.dwLowDateTime;
+//
+// // A Windows tick is 100 nanoseconds. Windows epoch 1601-01-01T00:00:00Z
+// // is 11644473600 seconds before Unix epoch 1970-01-01T00:00:00Z.
+// Timestamp timestamp;
+// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
+// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
+//
+// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
+//
+// long millis = System.currentTimeMillis();
+//
+// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
+// .setNanos((int) ((millis % 1000) * 1000000)).build();
+//
+// Example 5: Compute Timestamp from Python `datetime.datetime`.
+//
+// now = datetime.datetime.utcnow()
+// seconds = int(time.mktime(now.timetuple()))
+// nanos = now.microsecond * 1000
+// timestamp = Timestamp(seconds=seconds, nanos=nanos)
+@interface GPBTimestamp : GPBMessage
+
+// Represents seconds of UTC time since Unix epoch
+// 1970-01-01T00:00:00Z. Must be from from 0001-01-01T00:00:00Z to
+// 9999-12-31T23:59:59Z inclusive.
+@property(nonatomic, readwrite) int64_t seconds;
+
+// Non-negative fractions of a second at nanosecond resolution. Negative
+// second values with fractions must still have non-negative nanos values
+// that count forward in time. Must be from 0 to 999,999,999
+// inclusive.
+@property(nonatomic, readwrite) int32_t nanos;
+
+@end
+
+CF_EXTERN_C_END
diff --git a/objectivec/google/protobuf/Timestamp.pbobjc.m b/objectivec/google/protobuf/Timestamp.pbobjc.m
new file mode 100644
index 00000000..1c8d3c76
--- /dev/null
+++ b/objectivec/google/protobuf/Timestamp.pbobjc.m
@@ -0,0 +1,85 @@
+// Generated by the protocol buffer compiler. DO NOT EDIT!
+// source: google/protobuf/timestamp.proto
+
+#import "GPBProtocolBuffers_RuntimeSupport.h"
+
+#import "google/protobuf/Timestamp.pbobjc.h"
+
+#pragma mark - GPBTimestampRoot
+
+@implementation GPBTimestampRoot
+
+@end
+
+static GPBFileDescriptor *GPBTimestampRoot_FileDescriptor(void) {
+ // This is called by +initialize so there is no need to worry
+ // about thread safety of the singleton.
+ static GPBFileDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ descriptor = [[GPBFileDescriptor alloc] initWithPackage:@"google.protobuf"
+ syntax:GPBFileSyntaxProto3];
+ }
+ return descriptor;
+}
+
+#pragma mark - GPBTimestamp
+
+@implementation GPBTimestamp
+
+@dynamic seconds;
+@dynamic nanos;
+
+typedef struct GPBTimestamp_Storage {
+ uint32_t _has_storage_[1];
+ int32_t nanos;
+ int64_t seconds;
+} GPBTimestamp_Storage;
+
+// This method is threadsafe because it is initially called
+// in +initialize for each subclass.
++ (GPBDescriptor *)descriptor {
+ static GPBDescriptor *descriptor = NULL;
+ if (!descriptor) {
+ static GPBMessageFieldDescription fields[] = {
+ {
+ .name = "seconds",
+ .number = GPBTimestamp_FieldNumber_Seconds,
+ .hasIndex = 0,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeInt64,
+ .offset = offsetof(GPBTimestamp_Storage, seconds),
+ .defaultValue.valueInt64 = 0LL,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ {
+ .name = "nanos",
+ .number = GPBTimestamp_FieldNumber_Nanos,
+ .hasIndex = 1,
+ .flags = GPBFieldOptional,
+ .type = GPBTypeInt32,
+ .offset = offsetof(GPBTimestamp_Storage, nanos),
+ .defaultValue.valueInt32 = 0,
+ .typeSpecific.className = NULL,
+ .fieldOptions = NULL,
+ },
+ };
+ descriptor = [GPBDescriptor allocDescriptorForClass:[GPBTimestamp class]
+ rootClass:[GPBTimestampRoot class]
+ file:GPBTimestampRoot_FileDescriptor()
+ fields:fields
+ fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)
+ oneofs:NULL
+ oneofCount:0
+ enums:NULL
+ enumCount:0
+ ranges:NULL
+ rangeCount:0
+ storageSize:sizeof(GPBTimestamp_Storage)
+ wireFormat:NO];
+ }
+ return descriptor;
+}
+
+@end
+
diff --git a/protobuf-lite.pc.in b/protobuf-lite.pc.in
index 29c218e5..80f1f461 100644
--- a/protobuf-lite.pc.in
+++ b/protobuf-lite.pc.in
@@ -8,6 +8,4 @@ Description: Google's Data Interchange Format
Version: @VERSION@
Libs: -L${libdir} -lprotobuf-lite @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
Cflags: -I${includedir} @PTHREAD_CFLAGS@
-# Commented out because it crashes pkg-config *sigh*:
-# http://bugs.freedesktop.org/show_bug.cgi?id=13265
-# Conflicts: protobuf
+Conflicts: protobuf
diff --git a/protobuf.pc.in b/protobuf.pc.in
index 29f24877..49014903 100644
--- a/protobuf.pc.in
+++ b/protobuf.pc.in
@@ -9,6 +9,4 @@ Version: @VERSION@
Libs: -L${libdir} -lprotobuf @PTHREAD_CFLAGS@ @PTHREAD_LIBS@
Libs.private: @LIBS@
Cflags: -I${includedir} @PTHREAD_CFLAGS@
-# Commented out because it crashes pkg-config *sigh*:
-# http://bugs.freedesktop.org/show_bug.cgi?id=13265
-# Conflicts: protobuf-lite
+Conflicts: protobuf-lite
diff --git a/protoc-artifacts/Dockerfile b/protoc-artifacts/Dockerfile
new file mode 100644
index 00000000..fd35b89f
--- /dev/null
+++ b/protoc-artifacts/Dockerfile
@@ -0,0 +1,40 @@
+FROM centos:6.6
+
+RUN yum install -y git \
+ tar \
+ wget \
+ make \
+ autoconf \
+ curl-devel \
+ unzip \
+ automake \
+ libtool \
+ glibc-static.i686 \
+ glibc-devel \
+ glibc-devel.i686
+
+# Install Java 8
+RUN wget -q --no-cookies --no-check-certificate \
+ --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" "http://download.oracle.com/otn-pub/java/jdk/8u45-b14/jdk-8u45-linux-x64.tar.gz" \
+ -O - | tar xz -C /var/local
+ENV JAVA_HOME /var/local/jdk1.8.0_45
+ENV PATH $JAVA_HOME/bin:$PATH
+
+# Install Maven
+RUN wget -q http://apache.cs.utah.edu/maven/maven-3/3.3.3/binaries/apache-maven-3.3.3-bin.tar.gz -O - | \
+ tar xz -C /var/local
+ENV PATH /var/local/apache-maven-3.3.3/bin:$PATH
+
+# Install GCC 4.7 to support -static-libstdc++
+RUN wget http://people.centos.org/tru/devtools-1.1/devtools-1.1.repo -P /etc/yum.repos.d
+RUN bash -c 'echo "enabled=1" >> /etc/yum.repos.d/devtools-1.1.repo'
+RUN bash -c "sed -e 's/\$basearch/i386/g' /etc/yum.repos.d/devtools-1.1.repo > /etc/yum.repos.d/devtools-i386-1.1.repo"
+RUN sed -e 's/testing-/testing-i386-/g' -i /etc/yum.repos.d/devtools-i386-1.1.repo
+RUN yum install -y devtoolset-1.1 \
+ devtoolset-1.1-libstdc++-devel \
+ devtoolset-1.1-libstdc++-devel.i686
+
+RUN git clone --depth 1 https://github.com/google/protobuf.git
+
+# Start in devtoolset environment that uses GCC 4.7
+CMD ["scl", "enable", "devtoolset-1.1", "bash"]
diff --git a/protoc-artifacts/README.md b/protoc-artifacts/README.md
index 3a530197..06091cfe 100644
--- a/protoc-artifacts/README.md
+++ b/protoc-artifacts/README.md
@@ -63,9 +63,6 @@ deployment for all platforms. Currently the following platforms are supported:
- MSYS with MinGW32 (x86_32 only)
- MacOSX (x86_32 and x86_64)
-Remove any ``SNAPSHOT`` or ``pre`` suffix from the version string before
-deploying.
-
Use the following command to deploy artifacts for the host platform to a
staging repository.
```
@@ -90,6 +87,23 @@ When you have done deployment for all platforms, go to
https://oss.sonatype.org/#stagingRepositories, verify that the staging
repository has all the binaries, close and release this repository.
+### Tips for deploying on Linux
+We build on Centos 6.6 to provide a good compatibility for not very new
+systems. We have provided a ``Dockerfile`` under this directory to build the
+environment. It has been tested with Docker 1.6.1.
+
+To build a image:
+```
+$ docker build -t protoc-artifacts .
+```
+
+To run the image:
+```
+$ docker run -it --rm=true protoc-artifacts
+```
+
+The Protobuf repository has been cloned into ``/protobuf``.
+
### Tips for deploying on Windows
Under Windows the following error may occur: ``gpg: cannot open tty `no tty':
No such file or directory``. This can be fixed by configuring gpg through an
@@ -118,3 +132,12 @@ stored:
</activeProfiles>
</settings>
```
+
+### Tested build environments
+We have succesfully built artifacts on the following environments:
+- Linux x86_32 and x86_64:
+ - Centos 6.6 (within Docker 1.6.1)
+ - Ubuntu 14.04.2 64-bit
+- Windows x86_32: MSYS with ``mingw32-gcc-g++ 4.8.1-4`` on Windows 7 64-bit
+- Windows x86_64: Cygwin64 with ``mingw64-x86_64-gcc-g++ 4.8.3-1`` on Windows 7 64-bit
+- Mac OS X x86_32 and x86_64: Mac OS X 10.9.5
diff --git a/protoc-artifacts/build-protoc.sh b/protoc-artifacts/build-protoc.sh
index 96ca97c2..2f67c508 100755
--- a/protoc-artifacts/build-protoc.sh
+++ b/protoc-artifacts/build-protoc.sh
@@ -158,6 +158,9 @@ if [[ "$(uname)" == CYGWIN* ]]; then
elif [[ "$(uname)" == MINGW32* ]]; then
assertEq "$OS" windows $LINENO
assertEq "$ARCH" x86_32 $LINENO
+elif [[ "$(uname)" == MINGW64* ]]; then
+ assertEq "$OS" windows $LINENO
+ assertEq "$ARCH" x86_64 $LINENO
elif [[ "$(uname)" == Linux* ]]; then
if [[ "$OS" == linux ]]; then
if [[ "$ARCH" == x86_64 ]]; then
@@ -209,7 +212,7 @@ export CXXFLAGS LDFLAGS
TARGET_FILE=target/protoc.exe
cd "$WORKING_DIR"/.. && ./configure $CONFIGURE_ARGS &&
- cd src && make clean && make $MAKE_TARGET &&
+ cd src && make clean && make google/protobuf/stubs/pbconfig.h $MAKE_TARGET &&
cd "$WORKING_DIR" && mkdir -p target &&
(cp ../src/protoc $TARGET_FILE || cp ../src/protoc.exe $TARGET_FILE) ||
exit 1
diff --git a/python/MANIFEST.in b/python/MANIFEST.in
new file mode 100644
index 00000000..26088826
--- /dev/null
+++ b/python/MANIFEST.in
@@ -0,0 +1,14 @@
+prune google/protobuf/internal/import_test_package
+exclude google/protobuf/internal/*_pb2.py
+exclude google/protobuf/internal/*_test.py
+exclude google/protobuf/internal/*.proto
+exclude google/protobuf/internal/test_util.py
+
+recursive-exclude google *_test.py
+recursive-exclude google *_test.proto
+recursive-exclude google unittest*_pb2.py
+
+global-exclude *.dll
+global-exclude *.pyc
+global-exclude *.pyo
+global-exclude *.so
diff --git a/python/google/protobuf/internal/_parameterized.py b/python/google/protobuf/internal/_parameterized.py
index c44e77e4..400b2216 100755
--- a/python/google/protobuf/internal/_parameterized.py
+++ b/python/google/protobuf/internal/_parameterized.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/descriptor_database_test.py b/python/google/protobuf/internal/descriptor_database_test.py
index edf66a63..56fe14e9 100644
--- a/python/google/protobuf/internal/descriptor_database_test.py
+++ b/python/google/protobuf/internal/descriptor_database_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py
index 6d04ebaa..7d145f42 100644
--- a/python/google/protobuf/internal/descriptor_pool_test.py
+++ b/python/google/protobuf/internal/descriptor_pool_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index 549af088..335caee6 100755
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py
index 50fc1922..ccc5860b 100755
--- a/python/google/protobuf/internal/generator_test.py
+++ b/python/google/protobuf/internal/generator_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/message_factory_test.py b/python/google/protobuf/internal/message_factory_test.py
index 45ddcd26..626c3fc9 100644
--- a/python/google/protobuf/internal/message_factory_test.py
+++ b/python/google/protobuf/internal/message_factory_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index ce79b607..4ecaa1c7 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/proto_builder_test.py b/python/google/protobuf/internal/proto_builder_test.py
index 9229205a..b1e57f35 100644
--- a/python/google/protobuf/internal/proto_builder_test.py
+++ b/python/google/protobuf/internal/proto_builder_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 8f28f4d9..ae79c78b 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# Protocol Buffers - Google's data interchange format
diff --git a/python/google/protobuf/internal/service_reflection_test.py b/python/google/protobuf/internal/service_reflection_test.py
index e3f71545..de462124 100755
--- a/python/google/protobuf/internal/service_reflection_test.py
+++ b/python/google/protobuf/internal/service_reflection_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
@@ -81,7 +81,7 @@ class FooUnitTest(unittest.TestCase):
self.assertEqual('Method Bar not implemented.',
rpc_controller.failure_message)
self.assertEqual(None, self.callback_response)
-
+
class MyServiceImpl(unittest_pb2.TestService):
def Foo(self, rpc_controller, request, done):
self.foo_called = True
diff --git a/python/google/protobuf/internal/symbol_database_test.py b/python/google/protobuf/internal/symbol_database_test.py
index a58cb1a4..c888aff7 100644
--- a/python/google/protobuf/internal/symbol_database_test.py
+++ b/python/google/protobuf/internal/symbol_database_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/text_encoding_test.py b/python/google/protobuf/internal/text_encoding_test.py
index 48c30f01..27896b94 100755
--- a/python/google/protobuf/internal/text_encoding_test.py
+++ b/python/google/protobuf/internal/text_encoding_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 0135099d..bf7e06ee 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index d116920e..9337ae8a 100755
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
# -*- coding: utf-8 -*-
#
# Protocol Buffers - Google's data interchange format
diff --git a/python/google/protobuf/internal/wire_format_test.py b/python/google/protobuf/internal/wire_format_test.py
index e40a40cc..5cd7fcb9 100755
--- a/python/google/protobuf/internal/wire_format_test.py
+++ b/python/google/protobuf/internal/wire_format_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/python/setup.py b/python/setup.py
index fa98cd31..1764ec87 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# See README for usage instructions.
import sys
@@ -8,28 +8,29 @@ import subprocess
# We must use setuptools, not distutils, because we need to use the
# namespace_packages option for the "google" package.
try:
- from setuptools import setup, Extension
+ from setuptools import setup, Extension, find_packages
except ImportError:
try:
from ez_setup import use_setuptools
use_setuptools()
- from setuptools import setup, Extension
+ from setuptools import setup, Extension, find_packages
except ImportError:
sys.stderr.write(
"Could not import setuptools; make sure you have setuptools or "
- "ez_setup installed.\n")
+ "ez_setup installed.\n"
+ )
raise
+
from distutils.command.clean import clean as _clean
-if sys.version_info[0] >= 3:
- # Python 3
- from distutils.command.build_py import build_py_2to3 as _build_py
+
+if sys.version_info[0] == 3:
+ # Python 3
+ from distutils.command.build_py import build_py_2to3 as _build_py
else:
- # Python 2
- from distutils.command.build_py import build_py as _build_py
+ # Python 2
+ from distutils.command.build_py import build_py as _build_py
from distutils.spawn import find_executable
-maintainer_email = "protobuf@googlegroups.com"
-
# Find the Protocol Compiler.
if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']):
protoc = os.environ['PROTOC']
@@ -44,15 +45,15 @@ elif os.path.exists("../vsprojects/Release/protoc.exe"):
else:
protoc = find_executable("protoc")
+
def GetVersion():
"""Gets the version from google/protobuf/__init__.py
- Do not import google.protobuf.__init__ directly, because an installed protobuf
- library may be loaded instead.
+ Do not import google.protobuf.__init__ directly, because an installed
+ protobuf library may be loaded instead."""
- """
with open(os.path.join('google', 'protobuf', '__init__.py')) as version_file:
- exec(version_file.read())
+ exec(version_file.read(), globals())
return __version__
@@ -66,22 +67,24 @@ def generate_proto(source):
if (not os.path.exists(output) or
(os.path.exists(source) and
os.path.getmtime(source) > os.path.getmtime(output))):
- print ("Generating %s..." % output)
+ print("Generating %s..." % output)
if not os.path.exists(source):
sys.stderr.write("Can't find required file: %s\n" % source)
sys.exit(-1)
- if protoc == None:
+ if protoc is None:
sys.stderr.write(
- "protoc is not installed nor found in ../src. Please compile it "
- "or install the binary package.\n")
+ "protoc is not installed nor found in ../src. "
+ "Please compile it or install the binary package.\n"
+ )
sys.exit(-1)
- protoc_command = [ protoc, "-I../src", "-I.", "--python_out=.", source ]
+ protoc_command = [protoc, "-I../src", "-I.", "--python_out=.", source]
if subprocess.call(protoc_command) != 0:
sys.exit(-1)
+
def GenerateUnittestProtos():
generate_proto("../src/google/protobuf/unittest.proto")
generate_proto("../src/google/protobuf/unittest_custom_options.proto")
@@ -92,17 +95,18 @@ def GenerateUnittestProtos():
generate_proto("../src/google/protobuf/unittest_proto3_arena.proto")
generate_proto("google/protobuf/internal/descriptor_pool_test1.proto")
generate_proto("google/protobuf/internal/descriptor_pool_test2.proto")
- generate_proto("google/protobuf/internal/test_bad_identifiers.proto")
- generate_proto("google/protobuf/internal/missing_enum_values.proto")
- generate_proto("google/protobuf/internal/more_extensions.proto")
- generate_proto("google/protobuf/internal/more_extensions_dynamic.proto")
- generate_proto("google/protobuf/internal/more_messages.proto")
generate_proto("google/protobuf/internal/factory_test1.proto")
generate_proto("google/protobuf/internal/factory_test2.proto")
generate_proto("google/protobuf/internal/import_test_package/inner.proto")
generate_proto("google/protobuf/internal/import_test_package/outer.proto")
+ generate_proto("google/protobuf/internal/missing_enum_values.proto")
+ generate_proto("google/protobuf/internal/more_extensions.proto")
+ generate_proto("google/protobuf/internal/more_extensions_dynamic.proto")
+ generate_proto("google/protobuf/internal/more_messages.proto")
+ generate_proto("google/protobuf/internal/test_bad_identifiers.proto")
generate_proto("google/protobuf/pyext/python.proto")
+
class clean(_clean):
def run(self):
# Delete generated files in the code tree.
@@ -110,12 +114,13 @@ class clean(_clean):
for filename in filenames:
filepath = os.path.join(dirpath, filename)
if filepath.endswith("_pb2.py") or filepath.endswith(".pyc") or \
- filepath.endswith(".so") or filepath.endswith(".o") or \
- filepath.endswith('google/protobuf/compiler/__init__.py'):
+ filepath.endswith(".so") or filepath.endswith(".o") or \
+ filepath.endswith('google/protobuf/compiler/__init__.py'):
os.remove(filepath)
# _clean is an old-style class, so super() doesn't work.
_clean.run(self)
+
class build_py(_build_py):
def run(self):
# Generate necessary .proto file if it doesn't exist.
@@ -132,11 +137,11 @@ class build_py(_build_py):
# _build_py is an old-style class, so super() doesn't work.
_build_py.run(self)
# TODO(mrovner): Subclass to run 2to3 on some files only.
- # Tracing what https://wiki.python.org/moin/PortingPythonToPy3k's "Approach 2"
- # section on how to get 2to3 to run on source files during install under
- # Python 3. This class seems like a good place to put logic that calls
- # python3's distutils.util.run_2to3 on the subset of the files we have in our
- # release that are subject to conversion.
+ # Tracing what https://wiki.python.org/moin/PortingPythonToPy3k's
+ # "Approach 2" section on how to get 2to3 to run on source files during
+ # install under Python 3. This class seems like a good place to put logic
+ # that calls python3's distutils.util.run_2to3 on the subset of the files we
+ # have in our release that are subject to conversion.
# See code reference in previous code review.
if __name__ == '__main__':
@@ -145,61 +150,49 @@ if __name__ == '__main__':
if cpp_impl in sys.argv:
sys.argv.remove(cpp_impl)
# C++ implementation extension
- ext_module_list.append(Extension(
- "google.protobuf.pyext._message",
- [ "google/protobuf/pyext/descriptor.cc",
- "google/protobuf/pyext/descriptor_containers.cc",
- "google/protobuf/pyext/descriptor_pool.cc",
- "google/protobuf/pyext/message.cc",
- "google/protobuf/pyext/extension_dict.cc",
- "google/protobuf/pyext/repeated_scalar_container.cc",
- "google/protobuf/pyext/repeated_composite_container.cc" ],
- define_macros=[('GOOGLE_PROTOBUF_HAS_ONEOF', '1')],
- include_dirs = [ ".", "../src" ],
- libraries = [ "protobuf" ],
- library_dirs = [ '../src/.libs' ],
- ))
+ ext_module_list.append(
+ Extension(
+ "google.protobuf.pyext._message",
+ [
+ "google/protobuf/pyext/descriptor.cc",
+ "google/protobuf/pyext/descriptor_containers.cc",
+ "google/protobuf/pyext/descriptor_pool.cc",
+ "google/protobuf/pyext/extension_dict.cc",
+ "google/protobuf/pyext/message.cc",
+ "google/protobuf/pyext/repeated_composite_container.cc",
+ "google/protobuf/pyext/repeated_scalar_container.cc",
+ ],
+ define_macros=[('GOOGLE_PROTOBUF_HAS_ONEOF', '1')],
+ include_dirs=[".", "../src"],
+ libraries=['protobuf'],
+ library_dirs=['../src/.libs'],
+ )
+ )
os.environ['PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION'] = 'cpp'
- setup(name = 'protobuf',
- version = GetVersion(),
- packages = [ 'google' ],
- namespace_packages = [ 'google' ],
- test_suite = 'google.protobuf.internal',
- # Must list modules explicitly so that we don't install tests.
- py_modules = [
- 'google.protobuf.internal.api_implementation',
- 'google.protobuf.internal.containers',
- 'google.protobuf.internal.decoder',
- 'google.protobuf.internal.encoder',
- 'google.protobuf.internal.enum_type_wrapper',
- 'google.protobuf.internal.message_listener',
- 'google.protobuf.internal.python_message',
- 'google.protobuf.internal.type_checkers',
- 'google.protobuf.internal.wire_format',
- 'google.protobuf.descriptor',
- 'google.protobuf.descriptor_pb2',
- 'google.protobuf.compiler.plugin_pb2',
- 'google.protobuf.message',
- 'google.protobuf.descriptor_database',
- 'google.protobuf.descriptor_pool',
- 'google.protobuf.message_factory',
- 'google.protobuf.proto_builder',
- 'google.protobuf.pyext.cpp_message',
- 'google.protobuf.reflection',
- 'google.protobuf.service',
- 'google.protobuf.service_reflection',
- 'google.protobuf.symbol_database',
- 'google.protobuf.text_encoding',
- 'google.protobuf.text_format'],
- cmdclass = { 'clean': clean, 'build_py': build_py },
- install_requires = ['setuptools'],
- ext_modules = ext_module_list,
- url = 'https://developers.google.com/protocol-buffers/',
- maintainer = maintainer_email,
- maintainer_email = 'protobuf@googlegroups.com',
- license = 'New BSD License',
- description = 'Protocol Buffers',
- long_description =
- "Protocol Buffers are Google's data interchange format.",
- )
+ setup(
+ name='protobuf',
+ version=GetVersion(),
+ description='Protocol Buffers',
+ long_description="Protocol Buffers are Google's data interchange format",
+ url='https://developers.google.com/protocol-buffers/',
+ maintainer='protobuf@googlegroups.com',
+ maintainer_email='protobuf@googlegroups.com',
+ license='New BSD License',
+ classifiers=[
+ 'Programming Language :: Python :: 2.7',
+ ],
+ namespace_packages=['google'],
+ packages=find_packages(
+ exclude=[
+ 'import_test_package',
+ ],
+ ),
+ test_suite='google.protobuf.internal',
+ cmdclass={
+ 'clean': clean,
+ 'build_py': build_py,
+ },
+ install_requires=['setuptools'],
+ ext_modules=ext_module_list,
+ )
diff --git a/ruby/.gitignore b/ruby/.gitignore
index 80c978f2..bd8745dd 100644
--- a/ruby/.gitignore
+++ b/ruby/.gitignore
@@ -4,3 +4,5 @@ tags
lib/google/protobuf_java.jar
protobuf-jruby.iml
target/
+pkg/
+tmp/
diff --git a/ruby/Gemfile.lock b/ruby/Gemfile.lock
index 89deb47d..6f349276 100644
--- a/ruby/Gemfile.lock
+++ b/ruby/Gemfile.lock
@@ -1,7 +1,7 @@
PATH
remote: .
specs:
- google-protobuf (3.0.0.alpha.2)
+ google-protobuf (3.0.0.alpha.3.1.pre)
GEM
remote: https://rubygems.org/
diff --git a/ruby/README.md b/ruby/README.md
index d2fa76ab..16474322 100644
--- a/ruby/README.md
+++ b/ruby/README.md
@@ -63,7 +63,7 @@ To build this Ruby extension, you will need:
To Build the JRuby extension, you will need:
* Maven
-* The latest version of the protobuf java library
+* The latest version of the protobuf java library (see ../java/README.md)
* Install JRuby via rbenv or RVM
First switch to the desired platform with rbenv or RVM.
@@ -75,8 +75,9 @@ Then install the required Ruby gems:
Then build the Gem:
- $ rake gem
- $ gem install pkg/protobuf-$VERSION.gem
+ $ rake
+ $ rake clobber_package gem
+ $ gem install `ls pkg/google-protobuf-*.gem`
To run the specs:
diff --git a/ruby/Rakefile b/ruby/Rakefile
index 7c1d8495..c25103d8 100644
--- a/ruby/Rakefile
+++ b/ruby/Rakefile
@@ -6,6 +6,9 @@ require "rake/testtask"
spec = Gem::Specification.load("google-protobuf.gemspec")
if RUBY_PLATFORM == "java"
+ if `which mvn` == ''
+ raise ArgumentError, "maven needs to be installed"
+ end
task :clean do
system("mvn clean")
end
diff --git a/ruby/ext/google/protobuf_c/repeated_field.c b/ruby/ext/google/protobuf_c/repeated_field.c
index 8cf2e29b..5148ee87 100644
--- a/ruby/ext/google/protobuf_c/repeated_field.c
+++ b/ruby/ext/google/protobuf_c/repeated_field.c
@@ -47,6 +47,15 @@ RepeatedField* ruby_to_RepeatedField(VALUE _self) {
return self;
}
+static int index_position(VALUE _index, RepeatedField* repeated_field) {
+ int index = NUM2INT(_index);
+ if (index < 0 && repeated_field->size > 0) {
+ index = repeated_field->size + index;
+ }
+ return index;
+}
+
+
/*
* call-seq:
* RepeatedField.each(&block)
@@ -74,8 +83,7 @@ VALUE RepeatedField_each(VALUE _self) {
* call-seq:
* RepeatedField.[](index) => value
*
- * Accesses the element at the given index. Throws an exception on out-of-bounds
- * errors.
+ * Accesses the element at the given index. Returns nil on out-of-bounds
*/
VALUE RepeatedField_index(VALUE _self, VALUE _index) {
RepeatedField* self = ruby_to_RepeatedField(_self);
@@ -83,9 +91,9 @@ VALUE RepeatedField_index(VALUE _self, VALUE _index) {
upb_fieldtype_t field_type = self->field_type;
VALUE field_type_class = self->field_type_class;
- int index = NUM2INT(_index);
+ int index = index_position(_index, self);
if (index < 0 || index >= self->size) {
- rb_raise(rb_eRangeError, "Index out of range");
+ return Qnil;
}
void* memory = (void *) (((uint8_t *)self->elements) + index * element_size);
@@ -105,9 +113,9 @@ VALUE RepeatedField_index_set(VALUE _self, VALUE _index, VALUE val) {
VALUE field_type_class = self->field_type_class;
int element_size = native_slot_size(field_type);
- int index = NUM2INT(_index);
+ int index = index_position(_index, self);
if (index < 0 || index >= (INT_MAX - 1)) {
- rb_raise(rb_eRangeError, "Index out of range");
+ return Qnil;
}
if (index >= self->size) {
RepeatedField_reserve(self, index + 1);
diff --git a/ruby/ext/google/protobuf_c/storage.c b/ruby/ext/google/protobuf_c/storage.c
index 5b1549d2..2ad8bd74 100644
--- a/ruby/ext/google/protobuf_c/storage.c
+++ b/ruby/ext/google/protobuf_c/storage.c
@@ -155,7 +155,9 @@ void native_slot_set_value_and_case(upb_fieldtype_t type, VALUE type_class,
break;
}
case UPB_TYPE_MESSAGE: {
- if (CLASS_OF(value) != type_class) {
+ if (CLASS_OF(value) == CLASS_OF(Qnil)) {
+ value = Qnil;
+ } else if (CLASS_OF(value) != type_class) {
rb_raise(rb_eTypeError,
"Invalid type %s to assign to submessage field.",
rb_class2name(CLASS_OF(value)));
diff --git a/ruby/google-protobuf.gemspec b/ruby/google-protobuf.gemspec
index abbbde35..28cdebf5 100644
--- a/ruby/google-protobuf.gemspec
+++ b/ruby/google-protobuf.gemspec
@@ -4,10 +4,11 @@ Gem::Specification.new do |s|
s.licenses = ["BSD"]
s.summary = "Protocol Buffers"
s.description = "Protocol Buffers are Google's data interchange format."
+ s.homepage = "https://developers.google.com/protocol-buffers"
s.authors = ["Protobuf Authors"]
s.email = "protobuf@googlegroups.com"
s.require_paths = ["lib"]
- s.files = ["lib/google/protobuf.rb"]
+ s.files = `git ls-files -z`.split("\x0").find_all{|f| f =~ /lib\/.+\.rb/}
unless RUBY_PLATFORM == "java"
s.files += `git ls-files "*.c" "*.h" extconf.rb Makefile`.split
s.extensions= ["ext/google/protobuf_c/extconf.rb"]
diff --git a/ruby/lib/google/protobuf.rb b/ruby/lib/google/protobuf.rb
index 75869dd8..72797245 100644
--- a/ruby/lib/google/protobuf.rb
+++ b/ruby/lib/google/protobuf.rb
@@ -34,3 +34,5 @@ if RUBY_PLATFORM == "java"
else
require 'google/protobuf_c'
end
+
+require 'google/protobuf/repeated_field'
diff --git a/ruby/lib/google/protobuf/repeated_field.rb b/ruby/lib/google/protobuf/repeated_field.rb
new file mode 100644
index 00000000..5b934e56
--- /dev/null
+++ b/ruby/lib/google/protobuf/repeated_field.rb
@@ -0,0 +1,40 @@
+# 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.
+
+# add syntatic sugar on top of the core library
+module Google
+ module Protobuf
+ class RepeatedField
+
+ alias_method :size, :length
+
+ end
+ end
+end
diff --git a/ruby/pom.xml b/ruby/pom.xml
index 1630fe84..01f0e16b 100644
--- a/ruby/pom.xml
+++ b/ruby/pom.xml
@@ -78,7 +78,7 @@
<dependency>
<groupId>com.google.protobuf</groupId>
<artifactId>protobuf-java</artifactId>
- <version>3.0.0-pre</version>
+ <version>3.0.0-alpha-3-pre</version>
</dependency>
</dependencies>
</project>
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
index 04bc0b76..c7fd7aa7 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyMessage.java
@@ -246,16 +246,15 @@ public class RubyMessage extends RubyObject {
public IRubyObject dup(ThreadContext context) {
RubyMessage dup = (RubyMessage) metaClass.newInstance(context, Block.NULL_BLOCK);
IRubyObject value;
- for (Descriptors.FieldDescriptor fieldDescriptor : builder.getAllFields().keySet()) {
+ for (Descriptors.FieldDescriptor fieldDescriptor : this.descriptor.getFields()) {
if (fieldDescriptor.isRepeated()) {
- dup.repeatedFields.put(fieldDescriptor, getRepeatedField(context, fieldDescriptor));
- } else if (builder.hasField(fieldDescriptor)) {
- dup.fields.put(fieldDescriptor, wrapField(context, fieldDescriptor, builder.getField(fieldDescriptor)));
+ dup.addRepeatedField(fieldDescriptor, this.getRepeatedField(context, fieldDescriptor));
+ } else if (fields.containsKey(fieldDescriptor)) {
+ dup.fields.put(fieldDescriptor, fields.get(fieldDescriptor));
+ } else if (this.builder.hasField(fieldDescriptor)) {
+ dup.fields.put(fieldDescriptor, wrapField(context, fieldDescriptor, this.builder.getField(fieldDescriptor)));
}
}
- for (Descriptors.FieldDescriptor fieldDescriptor : fields.keySet()) {
- dup.fields.put(fieldDescriptor, fields.get(fieldDescriptor));
- }
for (Descriptors.FieldDescriptor fieldDescriptor : maps.keySet()) {
dup.maps.put(fieldDescriptor, maps.get(fieldDescriptor));
}
@@ -411,6 +410,7 @@ public class RubyMessage extends RubyObject {
for (int i = 0; i < count; i++) {
ret.push(context, wrapField(context, fieldDescriptor, this.builder.getRepeatedField(fieldDescriptor, i)));
}
+ addRepeatedField(fieldDescriptor, ret);
return ret;
}
@@ -659,14 +659,14 @@ public class RubyMessage extends RubyObject {
} else {
Descriptors.FieldDescriptor.Type fieldType = fieldDescriptor.getType();
IRubyObject typeClass = context.runtime.getObject();
+ boolean addValue = true;
if (fieldType == Descriptors.FieldDescriptor.Type.MESSAGE) {
typeClass = ((RubyDescriptor) getDescriptorForField(context, fieldDescriptor)).msgclass(context);
+ if (value.isNil()){
+ addValue = false;
+ }
} else if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
typeClass = ((RubyEnumDescriptor) getDescriptorForField(context, fieldDescriptor)).enummodule(context);
- }
- Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
- // Convert integer enum to symbol
- if (fieldType == Descriptors.FieldDescriptor.Type.ENUM) {
Descriptors.EnumDescriptor enumDescriptor = fieldDescriptor.getEnumType();
if (Utils.isRubyNum(value)) {
Descriptors.EnumValueDescriptor val =
@@ -674,7 +674,12 @@ public class RubyMessage extends RubyObject {
if (val.getIndex() != -1) value = context.runtime.newSymbol(val.getName());
}
}
- this.fields.put(fieldDescriptor, value);
+ if (addValue) {
+ Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
+ this.fields.put(fieldDescriptor, value);
+ } else {
+ this.fields.remove(fieldDescriptor);
+ }
}
}
return context.runtime.getNil();
diff --git a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
index 9788317a..84bf8956 100644
--- a/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
+++ b/ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java
@@ -108,8 +108,9 @@ public class RubyRepeatedField extends RubyObject {
*/
@JRubyMethod(name = "[]=")
public IRubyObject indexSet(ThreadContext context, IRubyObject index, IRubyObject value) {
+ int arrIndex = normalizeArrayIndex(index);
Utils.checkType(context, fieldType, value, (RubyModule) typeClass);
- this.storage.set(RubyNumeric.num2int(index), value);
+ this.storage.set(arrIndex, value);
return context.runtime.getNil();
}
@@ -117,12 +118,15 @@ public class RubyRepeatedField extends RubyObject {
* call-seq:
* RepeatedField.[](index) => value
*
- * Accesses the element at the given index. Throws an exception on out-of-bounds
- * errors.
+ * Accesses the element at the given index. Returns nil on out-of-bounds
*/
@JRubyMethod(name = "[]")
public IRubyObject index(ThreadContext context, IRubyObject index) {
- return this.storage.eltInternal(RubyNumeric.num2int(index));
+ int arrIndex = normalizeArrayIndex(index);
+ if (arrIndex < 0 || arrIndex >= this.storage.size()) {
+ return context.runtime.getNil();
+ }
+ return this.storage.eltInternal(arrIndex);
}
/*
@@ -134,8 +138,7 @@ public class RubyRepeatedField extends RubyObject {
@JRubyMethod(rest = true)
public IRubyObject insert(ThreadContext context, IRubyObject[] args) {
for (int i = 0; i < args.length; i++) {
- Utils.checkType(context, fieldType, args[i], (RubyModule) typeClass);
- this.storage.add(args[i]);
+ push(context, args[i]);
}
return context.runtime.getNil();
}
@@ -385,6 +388,15 @@ public class RubyRepeatedField extends RubyObject {
}
}
+ private int normalizeArrayIndex(IRubyObject index) {
+ int arrIndex = RubyNumeric.num2int(index);
+ int arrSize = this.storage.size();
+ if (arrIndex < 0 && arrSize > 0) {
+ arrIndex = arrSize + arrIndex;
+ }
+ return arrIndex;
+ }
+
private RubyArray storage;
private Descriptors.FieldDescriptor.Type fieldType;
private IRubyObject typeClass;
diff --git a/ruby/tests/basic.rb b/ruby/tests/basic.rb
index 1c3fb62c..1c2a03dc 100644
--- a/ruby/tests/basic.rb
+++ b/ruby/tests/basic.rb
@@ -154,6 +154,8 @@ module BasicTest
assert m.optional_bytes == "world"
m.optional_msg = TestMessage2.new(:foo => 42)
assert m.optional_msg == TestMessage2.new(:foo => 42)
+ m.optional_msg = nil
+ assert m.optional_msg == nil
end
def test_ctor_args
@@ -314,6 +316,17 @@ module BasicTest
assert l4 == [0, 0, 0, 0, 0, 42, 100, 101, 102]
end
+ def test_parent_rptfield
+ #make sure we set the RepeatedField and can add to it
+ m = TestMessage.new
+ assert m.repeated_string == []
+ m.repeated_string << 'ok'
+ m.repeated_string.push('ok2')
+ assert m.repeated_string == ['ok', 'ok2']
+ m.repeated_string += ['ok3']
+ assert m.repeated_string == ['ok', 'ok2', 'ok3']
+ end
+
def test_rptfield_msg
l = Google::Protobuf::RepeatedField.new(:message, TestMessage)
l.push TestMessage.new
@@ -377,6 +390,39 @@ module BasicTest
end
end
+ def test_rptfield_array_ducktyping
+ l = Google::Protobuf::RepeatedField.new(:int32)
+ length_methods = %w(count length size)
+ length_methods.each do |lm|
+ assert l.send(lm) == 0
+ end
+ # out of bounds returns a nil
+ assert l[0] == nil
+ assert l[1] == nil
+ assert l[-1] == nil
+ l.push 4
+ length_methods.each do |lm|
+ assert l.send(lm) == 1
+ end
+ assert l[0] == 4
+ assert l[1] == nil
+ assert l[-1] == 4
+ assert l[-2] == nil
+
+ l.push 2
+ length_methods.each do |lm|
+ assert l.send(lm) == 2
+ end
+ assert l[0] == 4
+ assert l[1] == 2
+ assert l[2] == nil
+ assert l[-1] == 2
+ assert l[-2] == 4
+ assert l[-3] == nil
+
+ #adding out of scope will backfill with empty objects
+ end
+
def test_map_basic
# allowed key types:
# :int32, :int64, :uint32, :uint64, :bool, :string, :bytes.
@@ -712,9 +758,12 @@ module BasicTest
m = TestMessage.new
m.optional_string = "hello"
m.optional_int32 = 42
- m.repeated_msg.push TestMessage2.new(:foo => 100)
- m.repeated_msg.push TestMessage2.new(:foo => 200)
-
+ tm1 = TestMessage2.new(:foo => 100)
+ tm2 = TestMessage2.new(:foo => 200)
+ m.repeated_msg.push tm1
+ assert m.repeated_msg[-1] == tm1
+ m.repeated_msg.push tm2
+ assert m.repeated_msg[-1] == tm2
m2 = m.dup
assert m == m2
m.optional_int32 += 1
@@ -827,7 +876,6 @@ module BasicTest
assert m['a.b'] == 4
end
-
def test_int_ranges
m = TestMessage.new
@@ -933,7 +981,6 @@ module BasicTest
assert_raise RangeError do
m.optional_uint64 = 1.5
end
-
end
def test_stress_test
diff --git a/src/Makefile.am b/src/Makefile.am
index 049583f5..12826d95 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -24,7 +24,17 @@ AM_LDFLAGS = $(PTHREAD_CFLAGS)
# If I say "dist_include_DATA", automake complains that $(includedir) is not
# a "legitimate" directory for DATA. Screw you, automake.
protodir = $(includedir)
-nobase_dist_proto_DATA = google/protobuf/descriptor.proto \
+nobase_dist_proto_DATA = google/protobuf/descriptor.proto \
+ google/protobuf/any.proto \
+ google/protobuf/api.proto \
+ google/protobuf/duration.proto \
+ google/protobuf/empty.proto \
+ google/protobuf/field_mask.proto \
+ google/protobuf/source_context.proto \
+ google/protobuf/struct.proto \
+ google/protobuf/timestamp.proto \
+ google/protobuf/type.proto \
+ google/protobuf/wrappers.proto \
google/protobuf/compiler/plugin.proto
# Not sure why these don't get cleaned automatically.
@@ -125,6 +135,7 @@ nobase_include_HEADERS = \
google/protobuf/compiler/java/java_generator.h \
google/protobuf/compiler/java/java_names.h \
google/protobuf/compiler/javanano/javanano_generator.h \
+ google/protobuf/compiler/objectivec/objectivec_generator.h \
google/protobuf/compiler/python/python_generator.h \
google/protobuf/compiler/ruby/ruby_generator.h \
google/protobuf/compiler/csharp/csharp_generator.h
@@ -288,6 +299,29 @@ libprotoc_la_SOURCES = \
google/protobuf/compiler/javanano/javanano_params.h \
google/protobuf/compiler/javanano/javanano_primitive_field.cc \
google/protobuf/compiler/javanano/javanano_primitive_field.h \
+ google/protobuf/compiler/objectivec/objectivec_enum.cc \
+ google/protobuf/compiler/objectivec/objectivec_enum.h \
+ google/protobuf/compiler/objectivec/objectivec_enum_field.cc \
+ google/protobuf/compiler/objectivec/objectivec_enum_field.h \
+ google/protobuf/compiler/objectivec/objectivec_extension.cc \
+ google/protobuf/compiler/objectivec/objectivec_extension.h \
+ google/protobuf/compiler/objectivec/objectivec_field.cc \
+ google/protobuf/compiler/objectivec/objectivec_field.h \
+ google/protobuf/compiler/objectivec/objectivec_file.cc \
+ google/protobuf/compiler/objectivec/objectivec_file.h \
+ google/protobuf/compiler/objectivec/objectivec_generator.cc \
+ google/protobuf/compiler/objectivec/objectivec_helpers.cc \
+ google/protobuf/compiler/objectivec/objectivec_helpers.h \
+ google/protobuf/compiler/objectivec/objectivec_map_field.cc \
+ google/protobuf/compiler/objectivec/objectivec_map_field.h \
+ google/protobuf/compiler/objectivec/objectivec_message.cc \
+ google/protobuf/compiler/objectivec/objectivec_message.h \
+ google/protobuf/compiler/objectivec/objectivec_message_field.cc \
+ google/protobuf/compiler/objectivec/objectivec_message_field.h \
+ google/protobuf/compiler/objectivec/objectivec_oneof.cc \
+ google/protobuf/compiler/objectivec/objectivec_oneof.h \
+ google/protobuf/compiler/objectivec/objectivec_primitive_field.cc \
+ google/protobuf/compiler/objectivec/objectivec_primitive_field.h \
google/protobuf/compiler/python/python_generator.cc \
google/protobuf/compiler/ruby/ruby_generator.cc \
google/protobuf/compiler/csharp/csharp_enum.cc \
@@ -521,6 +555,7 @@ protobuf_test_SOURCES = \
google/protobuf/compiler/cpp/cpp_plugin_unittest.cc \
google/protobuf/compiler/java/java_plugin_unittest.cc \
google/protobuf/compiler/java/java_doc_comment_unittest.cc \
+ google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc \
google/protobuf/compiler/python/python_plugin_unittest.cc \
google/protobuf/compiler/ruby/ruby_generator_unittest.cc \
google/protobuf/compiler/csharp/csharp_generator_unittest.cc \
diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto
index 5f29e01e..e1780fe5 100644
--- a/src/google/protobuf/any.proto
+++ b/src/google/protobuf/any.proto
@@ -36,11 +36,14 @@ option java_multiple_files = true;
option java_outer_classname = "AnyProto";
option java_package = "com.google.protobuf";
option csharp_namespace = "Google.ProtocolBuffers";
+option objc_class_prefix = "GPB";
+
// `Any` contains an arbitrary serialized message along with a URL
// that describes the type of the serialized message.
//
-//
+// The proto runtimes and/or compiler will eventually
+// provide utilities to pack/unpack Any values (projected Q1/15).
//
// # JSON
// The JSON representation of an `Any` value uses the regular
@@ -76,21 +79,24 @@ message Any {
// For URLs which use the schema `http`, `https`, or no schema, the
// following restrictions and interpretations apply:
//
- // * If no schema is provided, https is assumed.
+ // * If no schema is provided, `https` is assumed.
// * The last segment of the URL's path must represent the fully
// qualified name of the type (as in `path/google.protobuf.Duration`).
// * An HTTP GET on the URL must yield a [google.protobuf.Type][google.protobuf.Type]
// value in binary format, or produce an error.
// * Applications are allowed to cache lookup results based on the
// URL, or have them precompiled into a binary to avoid any
- // lookup. Therefore, binary compatibility need to be preserved
+ // lookup. Therefore, binary compatibility needs to be preserved
// on changes to types. (Use versioned type names to manage
// breaking changes.)
//
// Schemas other than `http`, `https` (or the empty schema) might be
// used with implementation specific semantics.
//
- //
+ // Types originating from the `google.*` package
+ // namespace should use `type.googleapis.com/full.type.name` (without
+ // schema and path). A type service will eventually become available which
+ // serves those URLs (projected Q2/15).
string type_url = 1;
// Must be valid serialized data of the above specified type.
diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto
new file mode 100644
index 00000000..f368c24d
--- /dev/null
+++ b/src/google/protobuf/api.proto
@@ -0,0 +1,105 @@
+// 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.
+syntax = "proto3";
+
+package google.protobuf;
+
+import "google/protobuf/source_context.proto";
+import "google/protobuf/type.proto";
+
+option java_multiple_files = true;
+option java_outer_classname = "ApiProto";
+option java_package = "com.google.protobuf";
+option objc_class_prefix = "GPB";
+
+
+// Api is a light-weight descriptor for a protocol buffer service.
+message Api {
+ // The fully qualified name of this api, including package name
+ // followed by the api's simple name.
+ string name = 1;
+
+ // The methods of this api, in unspecified order.
+ repeated Method methods = 2;
+
+ // Any metadata attached to the API.
+ repeated Option options = 3;
+
+ // A version string for this api. If specified, must have the form
+ // `major-version.minor-version`, as in `1.10`. If the minor version
+ // is omitted, it defaults to zero. If the entire version field is
+ // empty, the major version is derived from the package name, as
+ // outlined below. If the field is not empty, the version in the
+ // package name will be verified to be consistent with what is
+ // provided here.
+ //
+ // The versioning schema uses [semantic
+ // versioning](http://semver.org) where the major version number
+ // indicates a breaking change and the minor version an additive,
+ // non-breaking change. Both version numbers are signals to users
+ // what to expect from different versions, and should be carefully
+ // chosen based on the product plan.
+ //
+ // The major version is also reflected in the package name of the
+ // API, which must end in `v<major-version>`, as in
+ // `google.feature.v1`. For major versions 0 and 1, the suffix can
+ // be omitted. Zero major versions must only be used for
+ // experimental, none-GA apis.
+ //
+ // See also: [design doc](http://go/api-versioning).
+ //
+ //
+ string version = 4;
+
+ // Source context for the protocol buffer service represented by this
+ // message.
+ SourceContext source_context = 5;
+}
+
+// Method represents a method of an api.
+message Method {
+ // The simple name of this method.
+ string name = 1;
+
+ // A URL of the input message type.
+ string request_type_url = 2;
+
+ // If true, the request is streamed.
+ bool request_streaming = 3;
+
+ // The URL of the output message type.
+ string response_type_url = 4;
+
+ // If true, the response is streamed.
+ bool response_streaming = 5;
+
+ // Any metadata attached to the method.
+ repeated Option options = 6;
+}
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index bda37413..f7059d26 100755
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -29,6 +29,7 @@
// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <google/protobuf/arena.h>
+#include <google/protobuf/stubs/common.h>
#ifdef ADDRESS_SANITIZER
#include <sanitizer/asan_interface.h>
@@ -43,6 +44,12 @@ Arena::ThreadCache& Arena::thread_cache() {
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_ = { -1, NULL };
return thread_cache_;
}
+#elif defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+Arena::ThreadCache& Arena::thread_cache() {
+ static internal::ThreadLocalStorage<ThreadCache>* thread_cache_ =
+ new internal::ThreadLocalStorage<ThreadCache>();
+ return *thread_cache_->Get();
+}
#else
GOOGLE_THREAD_LOCAL Arena::ThreadCache Arena::thread_cache_ = { -1, NULL };
#endif
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index bb15e80c..b48bef92 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -373,6 +373,11 @@ class LIBPROTOBUF_EXPORT Arena {
// Thread local variables cannot be exposed through DLL interface but we can
// wrap them in static functions.
static ThreadCache& thread_cache();
+#elif defined(GOOGLE_PROTOBUF_OS_ANDROID) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+ // Android ndk does not support __thread keyword so we use a custom thread
+ // local storage class we implemented.
+ // iOS also does not support the __thread keyword.
+ static ThreadCache& thread_cache();
#else
static GOOGLE_THREAD_LOCAL ThreadCache thread_cache_;
static ThreadCache& thread_cache() { return thread_cache_; }
diff --git a/src/google/protobuf/arena_nc_test.py b/src/google/protobuf/arena_nc_test.py
index fc510a48..f390df36 100644
--- a/src/google/protobuf/arena_nc_test.py
+++ b/src/google/protobuf/arena_nc_test.py
@@ -1,4 +1,4 @@
-#! /usr/bin/python
+#! /usr/bin/env python
#
# Protocol Buffers - Google's data interchange format
# Copyright 2008 Google Inc. All rights reserved.
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index a2cbbdc6..e284c791 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -288,6 +288,7 @@ void CommandLineInterfaceTest::Run(const string& command) {
if (!disallow_plugins_) {
cli_.AllowPlugins("prefix-");
+#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
const char* possible_paths[] = {
// When building with shared libraries, libtool hides the real executable
// in .libs and puts a fake wrapper in the current directory.
@@ -316,6 +317,11 @@ void CommandLineInterfaceTest::Run(const string& command) {
}
if (plugin_path.empty()) {
+#else
+ string plugin_path = "third_party/protobuf/test_plugin";
+
+ if (access(plugin_path.c_str(), F_OK) != 0) {
+#endif // GOOGLE_THIRD_PARTY_PROTOBUF
GOOGLE_LOG(ERROR)
<< "Plugin executable not found. Plugin tests are likely to fail.";
} else {
diff --git a/src/google/protobuf/compiler/cpp/cpp_unittest.cc b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
index cc758cf5..9d14a924 100644
--- a/src/google/protobuf/compiler/cpp/cpp_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/cpp_unittest.cc
@@ -1392,6 +1392,12 @@ class OneofTest : public testing::Test {
case unittest::TestOneof2::kFooString:
EXPECT_TRUE(message.has_foo_string());
break;
+ case unittest::TestOneof2::kFooCord:
+ EXPECT_TRUE(message.has_foo_cord());
+ break;
+ case unittest::TestOneof2::kFooStringPiece:
+ EXPECT_TRUE(message.has_foo_string_piece());
+ break;
case unittest::TestOneof2::kFooBytes:
EXPECT_TRUE(message.has_foo_bytes());
break;
@@ -1404,6 +1410,9 @@ class OneofTest : public testing::Test {
case unittest::TestOneof2::kFoogroup:
EXPECT_TRUE(message.has_foogroup());
break;
+ case unittest::TestOneof2::kFooLazyMessage:
+ EXPECT_TRUE(message.has_foo_lazy_message());
+ break;
case unittest::TestOneof2::FOO_NOT_SET:
break;
}
diff --git a/src/google/protobuf/compiler/java/java_extension.cc b/src/google/protobuf/compiler/java/java_extension.cc
index 27cf416b..4db7085e 100644
--- a/src/google/protobuf/compiler/java/java_extension.cc
+++ b/src/google/protobuf/compiler/java/java_extension.cc
@@ -181,8 +181,9 @@ void ImmutableExtensionGenerator::Generate(io::Printer* printer) {
}
}
-void ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
+int ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
io::Printer* printer) {
+ int bytecode_estimate = 0;
if (descriptor_->extension_scope() == NULL &&
HasDescriptorMethods(descriptor_->file())) {
// Only applies to non-nested, non-lite extensions.
@@ -190,15 +191,18 @@ void ImmutableExtensionGenerator::GenerateNonNestedInitializationCode(
"$name$.internalInit(descriptor.getExtensions().get($index$));\n",
"name", UnderscoresToCamelCase(descriptor_),
"index", SimpleItoa(descriptor_->index()));
+ bytecode_estimate += 21;
}
+ return bytecode_estimate;
}
-void ImmutableExtensionGenerator::GenerateRegistrationCode(
+int ImmutableExtensionGenerator::GenerateRegistrationCode(
io::Printer* printer) {
printer->Print(
"registry.add($scope$.$name$);\n",
"scope", scope_,
"name", UnderscoresToCamelCase(descriptor_));
+ return 7;
}
} // namespace java
diff --git a/src/google/protobuf/compiler/java/java_extension.h b/src/google/protobuf/compiler/java/java_extension.h
index f1701fb5..bdd42263 100644
--- a/src/google/protobuf/compiler/java/java_extension.h
+++ b/src/google/protobuf/compiler/java/java_extension.h
@@ -67,8 +67,12 @@ class ExtensionGenerator {
virtual ~ExtensionGenerator() {}
virtual void Generate(io::Printer* printer) = 0;
- virtual void GenerateNonNestedInitializationCode(io::Printer* printer) = 0;
- virtual void GenerateRegistrationCode(io::Printer* printer) = 0;
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ virtual int GenerateNonNestedInitializationCode(io::Printer* printer) = 0;
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ virtual int GenerateRegistrationCode(io::Printer* printer) = 0;
protected:
static void InitTemplateVars(const FieldDescriptor* descriptor,
@@ -88,8 +92,8 @@ class ImmutableExtensionGenerator : public ExtensionGenerator {
virtual ~ImmutableExtensionGenerator();
virtual void Generate(io::Printer* printer);
- virtual void GenerateNonNestedInitializationCode(io::Printer* printer);
- virtual void GenerateRegistrationCode(io::Printer* printer);
+ virtual int GenerateNonNestedInitializationCode(io::Printer* printer);
+ virtual int GenerateRegistrationCode(io::Printer* printer);
protected:
const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/java/java_file.cc b/src/google/protobuf/compiler/java/java_file.cc
index f1e3cf67..4a1f4529 100644
--- a/src/google/protobuf/compiler/java/java_file.cc
+++ b/src/google/protobuf/compiler/java/java_file.cc
@@ -35,6 +35,7 @@
#include <google/protobuf/compiler/java/java_file.h>
#include <memory>
+#include <set>
#ifndef _SHARED_PTR_H
#include <google/protobuf/stubs/shared_ptr.h>
#endif
@@ -62,6 +63,19 @@ namespace java {
namespace {
+struct FieldDescriptorCompare {
+ bool operator ()(const FieldDescriptor* f1, const FieldDescriptor* f2) {
+ if(f1 == NULL) {
+ return false;
+ }
+ if(f2 == NULL) {
+ return true;
+ }
+ return f1->full_name() < f2->full_name();
+ }
+};
+
+typedef std::set<const FieldDescriptor*, FieldDescriptorCompare> FieldDescriptorSet;
// Recursively searches the given message to collect extensions.
// Returns true if all the extensions can be recognized. The extensions will be
@@ -69,7 +83,7 @@ namespace {
// Returns false when there are unknown fields, in which case the data in the
// extensions output parameter is not reliable and should be discarded.
bool CollectExtensions(const Message& message,
- vector<const FieldDescriptor*>* extensions) {
+ FieldDescriptorSet* extensions) {
const Reflection* reflection = message.GetReflection();
// There are unknown fields that could be extensions, thus this call fails.
@@ -79,7 +93,7 @@ bool CollectExtensions(const Message& message,
reflection->ListFields(message, &fields);
for (int i = 0; i < fields.size(); i++) {
- if (fields[i]->is_extension()) extensions->push_back(fields[i]);
+ if (fields[i]->is_extension()) extensions->insert(fields[i]);
if (GetJavaType(fields[i]) == JAVATYPE_MESSAGE) {
if (fields[i]->is_repeated()) {
@@ -106,7 +120,7 @@ bool CollectExtensions(const Message& message,
// in order to handle this case.
void CollectExtensions(const FileDescriptorProto& file_proto,
const DescriptorPool& alternate_pool,
- vector<const FieldDescriptor*>* extensions,
+ FieldDescriptorSet* extensions,
const string& file_data) {
if (!CollectExtensions(file_proto, extensions)) {
// There are unknown fields in the file_proto, which are probably
@@ -139,6 +153,36 @@ void CollectExtensions(const FileDescriptorProto& file_proto,
}
}
+// Our static initialization methods can become very, very large.
+// So large that if we aren't careful we end up blowing the JVM's
+// 64K bytes of bytecode/method. Fortunately, since these static
+// methods are executed only once near the beginning of a program,
+// there's usually plenty of stack space available and we can
+// extend our methods by simply chaining them to another method
+// with a tail call. This inserts the sequence call-next-method,
+// end this one, begin-next-method as needed.
+void MaybeRestartJavaMethod(io::Printer* printer,
+ int *bytecode_estimate,
+ int *method_num,
+ const char *chain_statement,
+ const char *method_decl) {
+
+ // The goal here is to stay under 64K bytes of jvm bytecode/method,
+ // since otherwise we hit a hardcoded limit in the jvm and javac will
+ // then fail with the error "code too large". This limit lets our
+ // estimates be off by a factor of two and still we're okay.
+ static const int bytesPerMethod = 1<<15; // aka 32K
+
+ if ((*bytecode_estimate) > bytesPerMethod) {
+ ++(*method_num);
+ printer->Print(chain_statement, "method_num", SimpleItoa(*method_num));
+ printer->Outdent();
+ printer->Print("}\n");
+ printer->Print(method_decl, "method_num", SimpleItoa(*method_num));
+ printer->Indent();
+ *bytecode_estimate = 0;
+ }
+}
} // namespace
@@ -270,9 +314,16 @@ void FileGenerator::Generate(io::Printer* printer) {
printer->Print(
"static {\n");
printer->Indent();
+ int bytecode_estimate = 0;
+ int method_num = 0;
for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ MaybeRestartJavaMethod(
+ printer,
+ &bytecode_estimate, &method_num,
+ "_clinit_autosplit_$method_num$();\n",
+ "private static void _clinit_autosplit_$method_num$() {\n");
}
printer->Outdent();
@@ -303,12 +354,24 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
SharedCodeGenerator shared_code_generator(file_);
shared_code_generator.GenerateDescriptors(printer);
+ int bytecode_estimate = 0;
+ int method_num = 0;
for (int i = 0; i < file_->message_type_count(); i++) {
- message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ bytecode_estimate += message_generators_[i]->GenerateStaticVariableInitializers(printer);
+ MaybeRestartJavaMethod(
+ printer,
+ &bytecode_estimate, &method_num,
+ "_clinit_autosplit_dinit_$method_num$();\n",
+ "private static void _clinit_autosplit_dinit_$method_num$() {\n");
}
for (int i = 0; i < file_->extension_count(); i++) {
- extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
+ bytecode_estimate += extension_generators_[i]->GenerateNonNestedInitializationCode(printer);
+ MaybeRestartJavaMethod(
+ printer,
+ &bytecode_estimate, &method_num,
+ "_clinit_autosplit_dinit_$method_num$();\n",
+ "private static void _clinit_autosplit_dinit_$method_num$() {\n");
}
// Proto compiler builds a DescriptorPool, which holds all the descriptors to
@@ -330,7 +393,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
file_->CopyTo(&file_proto);
string file_data;
file_proto.SerializeToString(&file_data);
- vector<const FieldDescriptor*> extensions;
+ FieldDescriptorSet extensions;
CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
if (extensions.size() > 0) {
@@ -339,10 +402,17 @@ void FileGenerator::GenerateDescriptorInitializationCodeForImmutable(
printer->Print(
"com.google.protobuf.ExtensionRegistry registry =\n"
" com.google.protobuf.ExtensionRegistry.newInstance();\n");
- for (int i = 0; i < extensions.size(); i++) {
+ FieldDescriptorSet::iterator it;
+ for (it = extensions.begin(); it != extensions.end(); it++) {
google::protobuf::scoped_ptr<ExtensionGenerator> generator(
- generator_factory_->NewExtensionGenerator(extensions[i]));
- generator->GenerateRegistrationCode(printer);
+ generator_factory_->NewExtensionGenerator(*it));
+ bytecode_estimate += generator->GenerateRegistrationCode(printer);
+ MaybeRestartJavaMethod(
+ printer,
+ &bytecode_estimate, &method_num,
+ "_clinit_autosplit_dinit_$method_num$(registry);\n",
+ "private static void _clinit_autosplit_dinit_$method_num$(\n"
+ " com.google.protobuf.ExtensionRegistry registry) {\n");
}
printer->Print(
"com.google.protobuf.Descriptors.FileDescriptor\n"
@@ -394,7 +464,7 @@ void FileGenerator::GenerateDescriptorInitializationCodeForMutable(io::Printer*
file_->CopyTo(&file_proto);
string file_data;
file_proto.SerializeToString(&file_data);
- vector<const FieldDescriptor*> extensions;
+ FieldDescriptorSet extensions;
CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
if (extensions.size() > 0) {
diff --git a/src/google/protobuf/compiler/java/java_message.cc b/src/google/protobuf/compiler/java/java_message.cc
index e982a17b..63df10b4 100644
--- a/src/google/protobuf/compiler/java/java_message.cc
+++ b/src/google/protobuf/compiler/java/java_message.cc
@@ -124,7 +124,7 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
// The descriptor for this type.
printer->Print(vars,
- "$private$static final com.google.protobuf.Descriptors.Descriptor\n"
+ "$private$static com.google.protobuf.Descriptors.Descriptor\n"
" internal_$identifier$_descriptor;\n");
// And the FieldAccessorTable.
@@ -139,8 +139,9 @@ void ImmutableMessageGenerator::GenerateStaticVariables(io::Printer* printer) {
}
}
-void ImmutableMessageGenerator::GenerateStaticVariableInitializers(
+int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
io::Printer* printer) {
+ int bytecode_estimate = 0;
if (HasDescriptorMethods(descriptor_)) {
map<string, string> vars;
vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
@@ -156,22 +157,25 @@ void ImmutableMessageGenerator::GenerateStaticVariableInitializers(
printer->Print(vars,
"internal_$identifier$_descriptor =\n"
" getDescriptor().getMessageTypes().get($index$);\n");
+ bytecode_estimate += 30;
} else {
printer->Print(vars,
"internal_$identifier$_descriptor =\n"
" internal_$parent$_descriptor.getNestedTypes().get($index$);\n");
+ bytecode_estimate += 30;
}
// And the FieldAccessorTable.
- GenerateFieldAccessorTableInitializer(printer);
+ bytecode_estimate += GenerateFieldAccessorTableInitializer(printer);
}
// Generate static member initializers for all nested types.
for (int i = 0; i < descriptor_->nested_type_count(); i++) {
// TODO(kenton): Reuse MessageGenerator objects?
- ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
+ bytecode_estimate += ImmutableMessageGenerator(descriptor_->nested_type(i), context_)
.GenerateStaticVariableInitializers(printer);
}
+ return bytecode_estimate;
}
void ImmutableMessageGenerator::
@@ -191,8 +195,9 @@ GenerateFieldAccessorTable(io::Printer* printer) {
" internal_$identifier$_fieldAccessorTable;\n");
}
-void ImmutableMessageGenerator::
+int ImmutableMessageGenerator::
GenerateFieldAccessorTableInitializer(io::Printer* printer) {
+ int bytecode_estimate = 10;
printer->Print(
"internal_$identifier$_fieldAccessorTable = new\n"
" com.google.protobuf.GeneratedMessage.FieldAccessorTable(\n"
@@ -203,6 +208,7 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) {
for (int i = 0; i < descriptor_->field_count(); i++) {
const FieldDescriptor* field = descriptor_->field(i);
const FieldGeneratorInfo* info = context_->GetFieldGeneratorInfo(field);
+ bytecode_estimate += 6;
printer->Print(
"\"$field_name$\", ",
"field_name", info->capitalized_name);
@@ -210,11 +216,13 @@ GenerateFieldAccessorTableInitializer(io::Printer* printer) {
for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
const OneofDescriptor* oneof = descriptor_->oneof_decl(i);
const OneofGeneratorInfo* info = context_->GetOneofGeneratorInfo(oneof);
+ bytecode_estimate += 6;
printer->Print(
"\"$oneof_name$\", ",
"oneof_name", info->capitalized_name);
}
printer->Print("});\n");
+ return bytecode_estimate;
}
// ===================================================================
diff --git a/src/google/protobuf/compiler/java/java_message.h b/src/google/protobuf/compiler/java/java_message.h
index 016fdd5d..58dd5f99 100644
--- a/src/google/protobuf/compiler/java/java_message.h
+++ b/src/google/protobuf/compiler/java/java_message.h
@@ -67,8 +67,8 @@ class MessageGenerator {
virtual void GenerateStaticVariables(io::Printer* printer) = 0;
// Output code which initializes the static variables generated by
- // GenerateStaticVariables().
- virtual void GenerateStaticVariableInitializers(io::Printer* printer) = 0;
+ // GenerateStaticVariables(). Returns an estimate of bytecode size.
+ virtual int GenerateStaticVariableInitializers(io::Printer* printer) = 0;
// Generate the class itself.
virtual void Generate(io::Printer* printer) = 0;
@@ -97,7 +97,9 @@ class ImmutableMessageGenerator : public MessageGenerator {
virtual void GenerateInterface(io::Printer* printer);
virtual void GenerateExtensionRegistrationCode(io::Printer* printer);
virtual void GenerateStaticVariables(io::Printer* printer);
- virtual void GenerateStaticVariableInitializers(io::Printer* printer);
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ virtual int GenerateStaticVariableInitializers(io::Printer* printer);
private:
enum UseMemoization {
@@ -106,7 +108,9 @@ class ImmutableMessageGenerator : public MessageGenerator {
};
void GenerateFieldAccessorTable(io::Printer* printer);
- void GenerateFieldAccessorTableInitializer(io::Printer* printer);
+
+ // Returns an estimate of the number of bytes the printed code will compile to
+ int GenerateFieldAccessorTableInitializer(io::Printer* printer);
void GenerateMessageSerializationMethods(io::Printer* printer);
void GenerateParseFromMethods(io::Printer* printer);
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum.cc b/src/google/protobuf/compiler/javanano/javanano_enum.cc
index f934b05f..c6e8dfe9 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_enum.cc
@@ -73,13 +73,45 @@ void EnumGenerator::Generate(io::Printer* printer) {
"// enum $classname$\n",
"classname", descriptor_->name());
+ const string classname = RenameJavaKeywords(descriptor_->name());
+
// Start of container interface
+ // If generating intdefs, we use the container interface as the intdef if
+ // present. Otherwise, we just make an empty @interface parallel to the
+ // constants.
+ bool use_intdef = params_.generate_intdefs();
bool use_shell_class = params_.java_enum_style();
- if (use_shell_class) {
- printer->Print(
- "public interface $classname$ {\n",
- "classname", RenameJavaKeywords(descriptor_->name()));
+ if (use_intdef) {
+ // @IntDef annotation so tools can enforce correctness
+ // Annotations will be discarded by the compiler
+ printer->Print("@java.lang.annotation.Retention("
+ "java.lang.annotation.RetentionPolicy.SOURCE)\n"
+ "@android.support.annotation.IntDef({\n");
printer->Indent();
+ for (int i = 0; i < canonical_values_.size(); i++) {
+ const string constant_name =
+ RenameJavaKeywords(canonical_values_[i]->name());
+ if (use_shell_class) {
+ printer->Print("$classname$.$name$,\n",
+ "classname", classname,
+ "name", constant_name);
+ } else {
+ printer->Print("$name$,\n", "name", constant_name);
+ }
+ }
+ printer->Outdent();
+ printer->Print("})\n");
+ }
+ if (use_shell_class || use_intdef) {
+ printer->Print(
+ "public $at_for_intdef$interface $classname$ {\n",
+ "classname", classname,
+ "at_for_intdef", use_intdef ? "@" : "");
+ if (use_shell_class) {
+ printer->Indent();
+ } else {
+ printer->Print("}\n\n");
+ }
}
// Canonical values
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
index 8a59d323..7666db38 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.cc
@@ -76,6 +76,10 @@ void SetEnumVariables(const Params& params,
internal::WireFormatLite::MakeTag(descriptor->number(),
internal::WireFormat::WireTypeForFieldType(descriptor->type())));
(*variables)["message_name"] = descriptor->containing_type()->name();
+ const EnumDescriptor* enum_type = descriptor->enum_type();
+ (*variables)["message_type_intdef"] = "@"
+ + ToJavaName(params, enum_type->name(), true,
+ enum_type->containing_type(), enum_type->file());
}
void LoadEnumValues(const Params& params,
@@ -116,8 +120,10 @@ EnumFieldGenerator::~EnumFieldGenerator() {}
void EnumFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
- printer->Print(variables_,
- "public $type$ $name$;\n");
+ if (params_.generate_intdefs()) {
+ printer->Print(variables_, "$message_type_intdef$\n");
+ }
+ printer->Print(variables_, "public $type$ $name$;\n");
if (params_.generate_has()) {
printer->Print(variables_,
@@ -256,12 +262,22 @@ AccessorEnumFieldGenerator::~AccessorEnumFieldGenerator() {}
void AccessorEnumFieldGenerator::
GenerateMembers(io::Printer* printer, bool /* unused lazy_init */) const {
+ printer->Print(variables_, "private int $name$_;\n");
+ if (params_.generate_intdefs()) {
+ printer->Print(variables_, "$message_type_intdef$\n");
+ }
printer->Print(variables_,
- "private int $name$_;\n"
"public int get$capitalized_name$() {\n"
" return $name$_;\n"
"}\n"
- "public $message_name$ set$capitalized_name$(int value) {\n"
+ "public $message_name$ set$capitalized_name$(");
+ if (params_.generate_intdefs()) {
+ printer->Print(variables_,
+ "\n"
+ " $message_type_intdef$ ");
+ }
+ printer->Print(variables_,
+ "int value) {\n"
" $name$_ = value;\n"
" $set_has$;\n"
" return this;\n"
@@ -499,6 +515,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
void RepeatedEnumFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n"
+ " cloned.$name$ = this.$name$.clone();\n"
+ "}\n");
+}
+
+void RepeatedEnumFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!com.google.protobuf.nano.InternalNano.equals(\n"
diff --git a/src/google/protobuf/compiler/javanano/javanano_enum_field.h b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
index 00adc61f..b94790d6 100644
--- a/src/google/protobuf/compiler/javanano/javanano_enum_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_enum_field.h
@@ -106,6 +106,7 @@ class RepeatedEnumFieldGenerator : public FieldGenerator {
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCodeCode(io::Printer* printer) const;
+ void GenerateFixClonedCode(io::Printer* printer) const;
private:
void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/javanano/javanano_extension.cc b/src/google/protobuf/compiler/javanano/javanano_extension.cc
index 754ed550..0b9d1d8d 100644
--- a/src/google/protobuf/compiler/javanano/javanano_extension.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_extension.cc
@@ -140,7 +140,7 @@ void ExtensionGenerator::Generate(io::Printer* printer) const {
" com.google.protobuf.nano.Extension.create$repeated$$ext_type$(\n"
" com.google.protobuf.nano.Extension.$type$,\n"
" $class$.class,\n"
- " $tag_params$);\n");
+ " $tag_params$L);\n");
}
} // namespace javanano
diff --git a/src/google/protobuf/compiler/javanano/javanano_field.h b/src/google/protobuf/compiler/javanano/javanano_field.h
index c2cf091c..57c221f4 100644
--- a/src/google/protobuf/compiler/javanano/javanano_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_field.h
@@ -83,6 +83,7 @@ class FieldGenerator {
virtual void GenerateSerializedSizeCode(io::Printer* printer) const = 0;
virtual void GenerateEqualsCode(io::Printer* printer) const = 0;
virtual void GenerateHashCodeCode(io::Printer* printer) const = 0;
+ virtual void GenerateFixClonedCode(io::Printer* printer) const {}
protected:
const Params& params_;
diff --git a/src/google/protobuf/compiler/javanano/javanano_generator.cc b/src/google/protobuf/compiler/javanano/javanano_generator.cc
index b5fbcd5f..ad215cb7 100644
--- a/src/google/protobuf/compiler/javanano/javanano_generator.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_generator.cc
@@ -152,6 +152,12 @@ bool JavaNanoGenerator::Generate(const FileDescriptor* file,
params.set_ignore_services(option_value == "true");
} else if (option_name == "parcelable_messages") {
params.set_parcelable_messages(option_value == "true");
+ } else if (option_name == "generate_clone") {
+ params.set_generate_clone(option_value == "true");
+ } else if (option_name == "generate_intdefs") {
+ params.set_generate_intdefs(option_value == "true");
+ } else if (option_name == "generate_clear") {
+ params.set_generate_clear(option_value == "true");
} else {
*error = "Ignore unknown javanano generator option: " + option_name;
}
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.cc b/src/google/protobuf/compiler/javanano/javanano_message.cc
index 707f6b84..a41da5ae 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message.cc
@@ -136,21 +136,37 @@ void MessageGenerator::Generate(io::Printer* printer) {
}
if (params_.store_unknown_fields() && params_.parcelable_messages()) {
printer->Print(
- " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$> {\n",
+ " com.google.protobuf.nano.android.ParcelableExtendableMessageNano<$classname$>",
"classname", descriptor_->name());
} else if (params_.store_unknown_fields()) {
printer->Print(
- " com.google.protobuf.nano.ExtendableMessageNano<$classname$> {\n",
+ " com.google.protobuf.nano.ExtendableMessageNano<$classname$>",
"classname", descriptor_->name());
} else if (params_.parcelable_messages()) {
printer->Print(
- " com.google.protobuf.nano.android.ParcelableMessageNano {\n");
+ " com.google.protobuf.nano.android.ParcelableMessageNano");
} else {
printer->Print(
- " com.google.protobuf.nano.MessageNano {\n");
+ " com.google.protobuf.nano.MessageNano");
+ }
+ if (params_.generate_clone()) {
+ printer->Print(" implements java.lang.Cloneable {\n");
+ } else {
+ printer->Print(" {\n");
}
printer->Indent();
+ if (params_.parcelable_messages()) {
+ printer->Print(
+ "\n"
+ "// Used by Parcelable\n"
+ "@SuppressWarnings({\"unused\"})\n"
+ "public static final android.os.Parcelable.Creator<$classname$> CREATOR =\n"
+ " new com.google.protobuf.nano.android.ParcelableMessageNanoCreator<\n"
+ " $classname$>($classname$.class);\n",
+ "classname", descriptor_->name());
+ }
+
// Nested types and extensions
for (int i = 0; i < descriptor_->extension_count(); i++) {
ExtensionGenerator(descriptor_->extension(i), params_).Generate(printer);
@@ -288,20 +304,28 @@ void MessageGenerator::Generate(io::Printer* printer) {
}
printer->Print("}\n");
} else {
+ printer->Print(
+ "\n"
+ "public $classname$() {\n",
+ "classname", descriptor_->name());
if (params_.generate_clear()) {
- printer->Print(
- "\n"
- "public $classname$() {\n"
- " clear();\n"
- "}\n",
- "classname", descriptor_->name());
+ printer->Print(" clear();\n");
+ } else {
+ printer->Indent();
+ GenerateFieldInitializers(printer);
+ printer->Outdent();
}
+ printer->Print("}\n");
}
// Other methods in this class
GenerateClear(printer);
+ if (params_.generate_clone()) {
+ GenerateClone(printer);
+ }
+
if (params_.generate_equals()) {
GenerateEquals(printer);
GenerateHashCode(printer);
@@ -495,6 +519,15 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
"classname", descriptor_->name());
printer->Indent();
+ GenerateFieldInitializers(printer);
+
+ printer->Outdent();
+ printer->Print(
+ " return this;\n"
+ "}\n");
+}
+
+void MessageGenerator::GenerateFieldInitializers(io::Printer* printer) {
// Clear bit fields.
int totalInts = (field_generators_.total_bits() + 31) / 32;
for (int i = 0; i < totalInts; i++) {
@@ -520,12 +553,34 @@ void MessageGenerator::GenerateClear(io::Printer* printer) {
if (params_.store_unknown_fields()) {
printer->Print("unknownFieldData = null;\n");
}
+ printer->Print("cachedSize = -1;\n");
+}
+
+void MessageGenerator::GenerateClone(io::Printer* printer) {
+ printer->Print(
+ "@Override\n"
+ "public $classname$ clone() {\n",
+ "classname", descriptor_->name());
+ printer->Indent();
+
+ printer->Print(
+ "$classname$ cloned;\n"
+ "try {\n"
+ " cloned = ($classname$) super.clone();\n"
+ "} catch (java.lang.CloneNotSupportedException e) {\n"
+ " throw new java.lang.AssertionError(e);\n"
+ "}\n",
+ "classname", descriptor_->name());
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i)).GenerateFixClonedCode(printer);
+ }
printer->Outdent();
printer->Print(
- " cachedSize = -1;\n"
- " return this;\n"
- "}\n");
+ " return cloned;\n"
+ "}\n"
+ "\n");
}
void MessageGenerator::GenerateEquals(io::Printer* printer) {
@@ -568,7 +623,11 @@ void MessageGenerator::GenerateEquals(io::Printer* printer) {
if (params_.store_unknown_fields()) {
printer->Print(
- "return unknownFieldDataEquals(other);\n");
+ "if (unknownFieldData == null || unknownFieldData.isEmpty()) {\n"
+ " return other.unknownFieldData == null || other.unknownFieldData.isEmpty();\n"
+ "} else {\n"
+ " return unknownFieldData.equals(other.unknownFieldData);\n"
+ "}");
} else {
printer->Print(
"return true;\n");
@@ -598,7 +657,9 @@ void MessageGenerator::GenerateHashCode(io::Printer* printer) {
if (params_.store_unknown_fields()) {
printer->Print(
- "result = 31 * result + unknownFieldDataHashCode();\n");
+ "result = 31 * result + \n"
+ " (unknownFieldData == null || unknownFieldData.isEmpty() ? 0 : \n"
+ " unknownFieldData.hashCode());\n");
}
printer->Print("return result;\n");
diff --git a/src/google/protobuf/compiler/javanano/javanano_message.h b/src/google/protobuf/compiler/javanano/javanano_message.h
index 6f25a3a0..281ec64f 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message.h
+++ b/src/google/protobuf/compiler/javanano/javanano_message.h
@@ -77,8 +77,10 @@ class MessageGenerator {
const FieldDescriptor* field);
void GenerateClear(io::Printer* printer);
+ void GenerateFieldInitializers(io::Printer* printer);
void GenerateEquals(io::Printer* printer);
void GenerateHashCode(io::Printer* printer);
+ void GenerateClone(io::Printer* printer);
const Params& params_;
const Descriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.cc b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
index 181c4060..d1d04b52 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.cc
@@ -127,6 +127,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
void MessageFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null) {\n"
+ " cloned.$name$ = this.$name$.clone();\n"
+ "}\n");
+}
+
+void MessageFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if (this.$name$ == null) { \n"
@@ -213,6 +221,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
void MessageOneofFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$oneof_name$ != null) {\n"
+ " cloned.$oneof_name$ = this.$oneof_name$.clone();\n"
+ "}\n");
+}
+
+void MessageOneofFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
GenerateOneofFieldEquals(descriptor_, variables_, printer);
}
@@ -313,6 +329,19 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
void RepeatedMessageFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n"
+ " cloned.$name$ = new $type$[this.$name$.length];\n"
+ " for (int i = 0; i < this.$name$.length; i++) {\n"
+ " if (this.$name$[i] != null) {\n"
+ " cloned.$name$[i] = this.$name$[i].clone();\n"
+ " }\n"
+ " }\n"
+ "}\n");
+}
+
+void RepeatedMessageFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
printer->Print(variables_,
"if (!com.google.protobuf.nano.InternalNano.equals(\n"
diff --git a/src/google/protobuf/compiler/javanano/javanano_message_field.h b/src/google/protobuf/compiler/javanano/javanano_message_field.h
index 6c615f5e..e074735c 100644
--- a/src/google/protobuf/compiler/javanano/javanano_message_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_message_field.h
@@ -58,6 +58,7 @@ class MessageFieldGenerator : public FieldGenerator {
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCodeCode(io::Printer* printer) const;
+ void GenerateFixClonedCode(io::Printer* printer) const;
private:
const FieldDescriptor* descriptor_;
@@ -80,6 +81,7 @@ class MessageOneofFieldGenerator : public FieldGenerator {
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCodeCode(io::Printer* printer) const;
+ void GenerateFixClonedCode(io::Printer* printer) const;
private:
const FieldDescriptor* descriptor_;
@@ -102,6 +104,7 @@ class RepeatedMessageFieldGenerator : public FieldGenerator {
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCodeCode(io::Printer* printer) const;
+ void GenerateFixClonedCode(io::Printer* printer) const;
private:
const FieldDescriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/javanano/javanano_params.h b/src/google/protobuf/compiler/javanano/javanano_params.h
index 4691f360..e3b4bb93 100644
--- a/src/google/protobuf/compiler/javanano/javanano_params.h
+++ b/src/google/protobuf/compiler/javanano/javanano_params.h
@@ -66,6 +66,8 @@ class Params {
bool parcelable_messages_;
bool reftypes_primitive_enums_;
bool generate_clear_;
+ bool generate_clone_;
+ bool generate_intdefs_;
public:
Params(const string & base_name) :
@@ -81,7 +83,9 @@ class Params {
ignore_services_(false),
parcelable_messages_(false),
reftypes_primitive_enums_(false),
- generate_clear_(true) {
+ generate_clear_(true),
+ generate_clone_(false),
+ generate_intdefs_(false) {
}
const string& base_name() const {
@@ -231,6 +235,20 @@ class Params {
bool generate_clear() const {
return generate_clear_;
}
+
+ void set_generate_clone(bool value) {
+ generate_clone_ = value;
+ }
+ bool generate_clone() const {
+ return generate_clone_;
+ }
+
+ void set_generate_intdefs(bool value) {
+ generate_intdefs_ = value;
+ }
+ bool generate_intdefs() const {
+ return generate_intdefs_;
+ }
};
} // namespace javanano
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
index 41bad0a6..978abf2c 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.cc
@@ -364,6 +364,14 @@ GenerateSerializedSizeCode(io::Printer* printer) const {
}
}
+void RepeatedPrimitiveFieldGenerator::
+GenerateFixClonedCode(io::Printer* printer) const {
+ printer->Print(variables_,
+ "if (this.$name$ != null && this.$name$.length > 0) {\n"
+ " cloned.$name$ = this.$name$.clone();\n"
+ "}\n");
+}
+
void PrimitiveFieldGenerator::
GenerateEqualsCode(io::Printer* printer) const {
// We define equality as serialized form equality. If generate_has(),
diff --git a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
index ca7116ff..a01981dd 100644
--- a/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
+++ b/src/google/protobuf/compiler/javanano/javanano_primitive_field.h
@@ -131,6 +131,7 @@ class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
void GenerateSerializedSizeCode(io::Printer* printer) const;
void GenerateEqualsCode(io::Printer* printer) const;
void GenerateHashCodeCode(io::Printer* printer) const;
+ void GenerateFixClonedCode(io::Printer* printer) const;
private:
void GenerateRepeatedDataSizeCode(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index bc2da38e..4815a726 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -37,6 +37,7 @@
#include <google/protobuf/compiler/javanano/javanano_generator.h>
#include <google/protobuf/compiler/ruby/ruby_generator.h>
#include <google/protobuf/compiler/csharp/csharp_generator.h>
+#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
int main(int argc, char* argv[]) {
@@ -74,5 +75,10 @@ int main(int argc, char* argv[]) {
cli.RegisterGenerator("--csharp_out", &csharp_generator,
"Generate C# source file.");
+ // Objective C
+ google::protobuf::compiler::objectivec::ObjectiveCGenerator objc_generator;
+ cli.RegisterGenerator("--objc_out", &objc_generator,
+ "Generate Objective C header and source.");
+
return cli.Run(argc, argv);
}
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
new file mode 100644
index 00000000..b7c720d2
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
@@ -0,0 +1,199 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor)
+ : descriptor_(descriptor),
+ name_(EnumName(descriptor_)) {
+ for (int i = 0; i < descriptor_->value_count(); i++) {
+ const EnumValueDescriptor* value = descriptor_->value(i);
+ const EnumValueDescriptor* canonical_value =
+ descriptor_->FindValueByNumber(value->number());
+
+ if (value == canonical_value) {
+ base_values_.push_back(value);
+ }
+ all_values_.push_back(value);
+ }
+}
+
+EnumGenerator::~EnumGenerator() {}
+
+void EnumGenerator::GenerateHeader(io::Printer* printer) {
+ string enum_comments;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ enum_comments = BuildCommentsString(location);
+ } else {
+ enum_comments = "";
+ }
+
+ printer->Print(
+ "#pragma mark - Enum $name$\n"
+ "\n",
+ "name", name_);
+
+ printer->Print("$comments$typedef GPB_ENUM($name$) {\n",
+ "comments", enum_comments,
+ "name", name_);
+ printer->Indent();
+
+ if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+ // Include the unknown value.
+ printer->Print(
+ "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
+ "name", name_);
+ }
+
+ for (int i = 0; i < all_values_.size(); i++) {
+ SourceLocation location;
+ if (all_values_[i]->GetSourceLocation(&location)) {
+ string comments = BuildCommentsString(location).c_str();
+ if (comments.length() > 0) {
+ if (i > 0) {
+ printer->Print("\n");
+ }
+ printer->Print(comments.c_str());
+ }
+ }
+
+ printer->Print(
+ "$name$ = $value$,\n",
+ "name", EnumValueName(all_values_[i]),
+ "value", SimpleItoa(all_values_[i]->number()));
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n"
+ "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
+ "\n"
+ "BOOL $name$_IsValidValue(int32_t value);\n"
+ "\n",
+ "name", name_);
+}
+
+void EnumGenerator::GenerateSource(io::Printer* printer) {
+ printer->Print(
+ "#pragma mark - Enum $name$\n"
+ "\n",
+ "name", name_);
+
+ printer->Print(
+ "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
+ " static GPBEnumDescriptor *descriptor = NULL;\n"
+ " if (!descriptor) {\n"
+ " static GPBMessageEnumValueDescription values[] = {\n",
+ "name", name_);
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+
+ // Note: For the TextFormat decode info, we can't use the enum value as
+ // the key because protocol buffer enums have 'allow_alias', which lets
+ // a value be used more than once. Instead, the index into the list of
+ // enum value descriptions is used. Note: start with -1 so the first one
+ // will be zero.
+ TextFormatDecodeData text_format_decode_data;
+ int enum_value_description_key = -1;
+
+ for (int i = 0; i < all_values_.size(); i++) {
+ ++enum_value_description_key;
+ string short_name(EnumValueShortName(all_values_[i]));
+ printer->Print("{ .name = \"$short_name$\", .number = $name$ },\n",
+ "short_name", short_name,
+ "name", EnumValueName(all_values_[i]));
+ if (UnCamelCaseEnumShortName(short_name) != all_values_[i]->name()) {
+ text_format_decode_data.AddString(enum_value_description_key, short_name,
+ all_values_[i]->name());
+ }
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(" };\n");
+ if (text_format_decode_data.num_entries() == 0) {
+ printer->Print(
+ " descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+ " values:values\n"
+ " valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
+ " enumVerifier:$name$_IsValidValue];\n",
+ "name", name_);
+ } else {
+ printer->Print(
+ " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
+ " descriptor = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
+ " values:values\n"
+ " valueCount:sizeof(values) / sizeof(GPBMessageEnumValueDescription)\n"
+ " enumVerifier:$name$_IsValidValue\n"
+ " extraTextFormatInfo:extraTextFormatInfo];\n",
+ "name", name_,
+ "extraTextFormatInfo", CEscape(text_format_decode_data.Data()));
+ }
+ printer->Print(
+ " }\n"
+ " return descriptor;\n"
+ "}\n\n");
+
+ printer->Print(
+ "BOOL $name$_IsValidValue(int32_t value__) {\n"
+ " switch (value__) {\n",
+ "name", name_);
+
+ for (int i = 0; i < base_values_.size(); i++) {
+ printer->Print(
+ " case $name$:\n",
+ "name", EnumValueName(base_values_[i]));
+ }
+
+ printer->Print(
+ " return YES;\n"
+ " default:\n"
+ " return NO;\n"
+ " }\n"
+ "}\n\n");
+}
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
new file mode 100644
index 00000000..2dc5547b
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum.h
@@ -0,0 +1,73 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer; // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumGenerator {
+ public:
+ EnumGenerator(const EnumDescriptor* descriptor);
+ ~EnumGenerator();
+
+ void GenerateHeader(io::Printer* printer);
+ void GenerateSource(io::Printer* printer);
+
+ const string& name() const { return name_; }
+
+ private:
+ const EnumDescriptor* descriptor_;
+ vector<const EnumValueDescriptor*> base_values_;
+ vector<const EnumValueDescriptor*> all_values_;
+ const string name_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
new file mode 100644
index 00000000..739282b2
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
@@ -0,0 +1,129 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+void SetEnumVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ string type = EnumName(descriptor->enum_type());
+ (*variables)["storage_type"] = type;
+ // TODO(thomasvl): Make inclusion of descriptor compile time and output
+ // both of these. Note: Extensions currently have to have the EnumDescription.
+ (*variables)["enum_verifier"] = type + "_IsValidValue";
+ (*variables)["enum_desc_func"] = type + "_EnumDescriptor";
+
+ const Descriptor* msg_descriptor = descriptor->containing_type();
+ (*variables)["owning_message_class"] = ClassName(msg_descriptor);
+}
+} // namespace
+
+EnumFieldGenerator::EnumFieldGenerator(const FieldDescriptor* descriptor)
+ : SingleFieldGenerator(descriptor) {
+ SetEnumVariables(descriptor, &variables_);
+}
+
+EnumFieldGenerator::~EnumFieldGenerator() {}
+
+void EnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
+ io::Printer* printer) const {
+ // TODO(thomasvl): Output the CPP check to use descFunc or validator based
+ // on final compile.
+ printer->Print(
+ variables_,
+ " .typeSpecific.enumDescFunc = $enum_desc_func$,\n");
+}
+
+void EnumFieldGenerator::GenerateCFunctionDeclarations(
+ io::Printer* printer) const {
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return;
+
+ printer->Print(
+ variables_,
+ "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message);\n"
+ "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n"
+ "\n");
+}
+
+void EnumFieldGenerator::GenerateCFunctionImplementations(
+ io::Printer* printer) const {
+ if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return;
+
+ printer->Print(
+ variables_,
+ "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n"
+ " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
+ " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
+ " return GPBGetInt32IvarWithField(message, field);\n"
+ "}\n"
+ "\n"
+ "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value) {\n"
+ " GPBDescriptor *descriptor = [$owning_message_class$ descriptor];\n"
+ " GPBFieldDescriptor *field = [descriptor fieldWithNumber:$field_number_name$];\n"
+ " GPBSetInt32IvarWithFieldInternal(message, field, value, descriptor.file.syntax);\n"
+ "}\n"
+ "\n");
+}
+
+RepeatedEnumFieldGenerator::RepeatedEnumFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : RepeatedFieldGenerator(descriptor) {
+ SetEnumVariables(descriptor, &variables_);
+ variables_["array_storage_type"] = "GPBEnumArray";
+}
+
+RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
+
+void RepeatedEnumFieldGenerator::GenerateFieldDescriptionTypeSpecific(
+ io::Printer* printer) const {
+ // TODO(thomasvl): Output the CPP check to use descFunc or validator based
+ // on final compile.
+ printer->Print(
+ variables_,
+ " .typeSpecific.enumDescFunc = $enum_desc_func$,\n");
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
new file mode 100644
index 00000000..2d5822bb
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
@@ -0,0 +1,77 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumFieldGenerator : public SingleFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ public:
+ virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+ virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
+ virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
+
+ protected:
+ EnumFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~EnumFieldGenerator();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
+};
+
+class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ public:
+ virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+
+ protected:
+ RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~RepeatedEnumFieldGenerator();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
new file mode 100644
index 00000000..b19c1b45
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
@@ -0,0 +1,166 @@
+// 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.
+
+#include <iostream>
+
+#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+ExtensionGenerator::ExtensionGenerator(const string& root_class_name,
+ const FieldDescriptor* descriptor)
+ : method_name_(ExtensionMethodName(descriptor)),
+ root_class_and_method_name_(root_class_name + "_" + method_name_),
+ descriptor_(descriptor) {
+ // Extensions can be filtered via the method they are accessed off the
+ // file's Root with.
+ if (FilterClass(root_class_and_method_name_)) {
+ filter_reason_ =
+ string("Extension |") + root_class_and_method_name_ + "| was not whitelisted.";
+ } else {
+ // Extensions that add a Message field also require that field be allowed
+ // by the filter, or they aren't usable.
+ ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
+ if (objc_type == OBJECTIVECTYPE_MESSAGE) {
+ const string message_class_name(ClassName(descriptor_->message_type()));
+ if (FilterClass(message_class_name)) {
+ filter_reason_ = string("Extension |") + root_class_and_method_name_ +
+ "| needs message |" + message_class_name +
+ "|, which was not whitelisted.";
+ }
+ }
+ }
+ if (descriptor->is_map()) {
+ // NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+ // error case, so it seem to be ok to use as a back door for errors.
+ cerr << "error: Extension is a map<>!"
+ << " That used to be blocked by the compiler." << endl;
+ cerr.flush();
+ abort();
+ }
+}
+
+ExtensionGenerator::~ExtensionGenerator() {}
+
+void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
+ WriteClassNameToClassList(root_class_and_method_name_);
+ if (IsFiltered()) {
+ printer->Print("// $filter_reason$\n\n", "filter_reason", filter_reason_);
+ return;
+ }
+ map<string, string> vars;
+ vars["method_name"] = method_name_;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ vars["comments"] = BuildCommentsString(location);
+ } else {
+ vars["comments"] = "";
+ }
+ printer->Print(vars,
+ "$comments$"
+ "+ (GPBExtensionField*)$method_name$;\n");
+}
+
+void ExtensionGenerator::GenerateStaticVariablesInitialization(
+ io::Printer* printer, bool* out_generated, bool root) {
+ if (IsFiltered()) {
+ return;
+ }
+ *out_generated = true;
+ map<string, string> vars;
+ vars["root_class_and_method_name"] = root_class_and_method_name_;
+ vars["extended_type"] = ClassName(descriptor_->containing_type());
+ vars["number"] = SimpleItoa(descriptor_->number());
+
+ std::vector<string> options;
+ if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated");
+ if (descriptor_->options().packed()) options.push_back("GPBExtensionPacked");
+ if (descriptor_->containing_type()->options().message_set_wire_format())
+ options.push_back("GPBExtensionSetWireFormat");
+
+ vars["options"] = BuildFlagsString(options);
+
+ ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
+ string singular_type;
+ if (objc_type == OBJECTIVECTYPE_MESSAGE) {
+ vars["type"] = string("GPBStringifySymbol(") +
+ ClassName(descriptor_->message_type()) + ")";
+ } else {
+ vars["type"] = "NULL";
+ }
+
+ vars["default_name"] = GPBValueFieldName(descriptor_);
+ if (descriptor_->is_repeated()) {
+ vars["default"] = "nil";
+ } else {
+ vars["default"] = DefaultValue(descriptor_);
+ }
+ string type = GetCapitalizedType(descriptor_);
+ vars["extension_type"] = string("GPBType") + type;
+
+ if (objc_type == OBJECTIVECTYPE_ENUM) {
+ vars["enum_desc_func_name"] =
+ EnumName(descriptor_->enum_type()) + "_EnumDescriptor";
+ } else {
+ vars["enum_desc_func_name"] = "NULL";
+ }
+
+ printer->Print(vars,
+ "{\n"
+ " .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
+ " .type = $extension_type$,\n"
+ " .extendedClass = GPBStringifySymbol($extended_type$),\n"
+ " .fieldNumber = $number$,\n"
+ " .defaultValue.$default_name$ = $default$,\n"
+ " .messageOrGroupClassName = $type$,\n"
+ " .options = $options$,\n"
+ " .enumDescriptorFunc = $enum_desc_func_name$,\n"
+ "},\n");
+}
+
+void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) {
+ if (IsFiltered()) {
+ return;
+ }
+ printer->Print(
+ "[registry addExtension:$root_class_and_method_name$];\n",
+ "root_class_and_method_name", root_class_and_method_name_);
+}
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
new file mode 100644
index 00000000..d17f5be9
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_extension.h
@@ -0,0 +1,73 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__
+
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+class FieldDescriptor; // descriptor.h
+namespace io {
+class Printer; // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class ExtensionGenerator {
+ public:
+ explicit ExtensionGenerator(const string& root_class_name,
+ const FieldDescriptor* descriptor);
+ ~ExtensionGenerator();
+
+ void GenerateMembersHeader(io::Printer* printer);
+ void GenerateStaticVariablesInitialization(io::Printer* printer,
+ bool* out_generated, bool root);
+ void GenerateRegistrationSource(io::Printer* printer);
+
+ bool IsFiltered() const { return filter_reason_.length() > 0; }
+
+ private:
+ string method_name_;
+ string root_class_and_method_name_;
+ string filter_reason_;
+ const FieldDescriptor* descriptor_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+};
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
new file mode 100644
index 00000000..b071ce5d
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.cc
@@ -0,0 +1,474 @@
+// 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.
+
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#ifndef htonl
+#include <netinet/in.h>
+#endif
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+void SetCommonFieldVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ string camel_case_name = FieldName(descriptor);
+ string raw_field_name;
+ if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
+ raw_field_name = descriptor->message_type()->name();
+ } else {
+ raw_field_name = descriptor->name();
+ }
+ // The logic here has to match -[GGPBFieldDescriptor textFormatName].
+ const string un_camel_case_name(
+ UnCamelCaseFieldName(camel_case_name, descriptor));
+ const bool needs_custom_name = (raw_field_name != un_camel_case_name);
+
+ SourceLocation location;
+ if (descriptor->GetSourceLocation(&location)) {
+ (*variables)["comments"] = BuildCommentsString(location);
+ } else {
+ (*variables)["comments"] = "\n";
+ }
+ const string& classname = ClassName(descriptor->containing_type());
+ (*variables)["classname"] = classname;
+ (*variables)["name"] = camel_case_name;
+ const string& capitalized_name = FieldNameCapitalized(descriptor);
+ (*variables)["capitalized_name"] = capitalized_name;
+ (*variables)["raw_field_name"] = raw_field_name;
+ (*variables)["field_number_name"] =
+ classname + "_FieldNumber_" + capitalized_name;
+ (*variables)["field_number"] = SimpleItoa(descriptor->number());
+ (*variables)["has_index"] = SimpleItoa(descriptor->index());
+ (*variables)["field_type"] = GetCapitalizedType(descriptor);
+ std::vector<string> field_flags;
+ if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
+ if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
+ if (descriptor->is_optional()) field_flags.push_back("GPBFieldOptional");
+ if (descriptor->options().packed()) field_flags.push_back("GPBFieldPacked");
+
+ // ObjC custom flags.
+ if (descriptor->has_default_value())
+ field_flags.push_back("GPBFieldHasDefaultValue");
+ if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom");
+ if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
+ // TODO(thomasvl): Output the CPP check to use descFunc or validator based
+ // on final compile.
+ field_flags.push_back("GPBFieldHasEnumDescriptor");
+ }
+
+ (*variables)["fieldflags"] = BuildFlagsString(field_flags);
+
+ (*variables)["default"] = DefaultValue(descriptor);
+ (*variables)["default_name"] = GPBValueFieldName(descriptor);
+
+ (*variables)["typeSpecific_name"] = "className";
+ (*variables)["typeSpecific_value"] = "NULL";
+
+ string field_options = descriptor->options().SerializeAsString();
+ // Must convert to a standard byte order for packing length into
+ // a cstring.
+ uint32_t length = htonl(field_options.length());
+ if (length > 0) {
+ string bytes((const char*)&length, sizeof(length));
+ bytes.append(field_options);
+ string options_str = "\"" + CEscape(bytes) + "\"";
+ (*variables)["fieldoptions"] = "\"" + CEscape(bytes) + "\"";
+ } else {
+ (*variables)["fieldoptions"] = "";
+ }
+
+ // Clear some common things so they can be set just when needed.
+ (*variables)["storage_attribute"] = "";
+}
+
+// A field generator that writes nothing.
+class EmptyFieldGenerator : public FieldGenerator {
+ public:
+ EmptyFieldGenerator(const FieldDescriptor* descriptor, const string& reason)
+ : FieldGenerator(descriptor), reason_(reason) {}
+ virtual ~EmptyFieldGenerator() {}
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const {}
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const {
+ string name = FieldName(descriptor_);
+ string type;
+ switch (GetObjectiveCType(descriptor_)) {
+ case OBJECTIVECTYPE_MESSAGE:
+ type = ClassName(descriptor_->message_type()) + " *";
+ break;
+
+ case OBJECTIVECTYPE_ENUM:
+ type = EnumName(descriptor_->enum_type()) + " ";
+ break;
+
+ default:
+ type = string(descriptor_->type_name()) + " ";
+ break;
+ }
+ printer->Print("// Field |$type$$name$| $reason$\n\n", "type", type, "name",
+ name, "reason", reason_);
+ }
+
+ virtual void GenerateFieldNumberConstant(io::Printer* printer) const {}
+ virtual void GeneratePropertyImplementation(io::Printer* printer) const {}
+ virtual void GenerateFieldDescription(io::Printer* printer) const {}
+
+ virtual bool WantsHasProperty(void) const { return false; }
+
+ private:
+ string reason_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EmptyFieldGenerator);
+};
+
+} // namespace
+
+FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
+ FieldGenerator* result = NULL;
+ if (field->is_repeated()) {
+ switch (GetObjectiveCType(field)) {
+ case OBJECTIVECTYPE_MESSAGE: {
+ string type = ClassName(field->message_type());
+ if (FilterClass(type)) {
+ string reason =
+ "Filtered by |" + type + "| not being whitelisted.";
+ result = new EmptyFieldGenerator(field, reason);
+ } else if (field->is_map()) {
+ result = new MapFieldGenerator(field);
+ } else {
+ result = new RepeatedMessageFieldGenerator(field);
+ }
+ break;
+ }
+ case OBJECTIVECTYPE_ENUM:
+ result = new RepeatedEnumFieldGenerator(field);
+ break;
+ default:
+ result = new RepeatedPrimitiveFieldGenerator(field);
+ break;
+ }
+ } else {
+ switch (GetObjectiveCType(field)) {
+ case OBJECTIVECTYPE_MESSAGE: {
+ string type = ClassName(field->message_type());
+ if (FilterClass(type)) {
+ string reason =
+ "Filtered by |" + type + "| not being whitelisted.";
+ result = new EmptyFieldGenerator(field, reason);
+ } else {
+ result = new MessageFieldGenerator(field);
+ }
+ break;
+ }
+ case OBJECTIVECTYPE_ENUM:
+ result = new EnumFieldGenerator(field);
+ break;
+ default:
+ if (IsReferenceType(field)) {
+ result = new PrimitiveObjFieldGenerator(field);
+ } else {
+ result = new PrimitiveFieldGenerator(field);
+ }
+ break;
+ }
+ }
+ result->FinishInitialization();
+ return result;
+}
+
+
+FieldGenerator::FieldGenerator(const FieldDescriptor* descriptor)
+ : descriptor_(descriptor) {
+ SetCommonFieldVariables(descriptor, &variables_);
+}
+
+FieldGenerator::~FieldGenerator() {}
+
+void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "$field_number_name$ = $field_number$,\n");
+}
+
+void FieldGenerator::GenerateCFunctionDeclarations(
+ io::Printer* printer) const {
+ // Nothing
+}
+
+void FieldGenerator::GenerateCFunctionImplementations(
+ io::Printer* printer) const {
+ // Nothing
+}
+
+void FieldGenerator::GenerateFieldDescription(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ "{\n"
+ " .name = \"$name$\",\n"
+ " .number = $field_number_name$,\n"
+ " .hasIndex = $has_index$,\n"
+ " .flags = $fieldflags$,\n"
+ " .type = GPBType$field_type$,\n"
+ " .offset = offsetof($classname$_Storage, $name$),\n"
+ " .defaultValue.$default_name$ = $default$,\n");
+
+ // " .typeSpecific.value* = [something],"
+ GenerateFieldDescriptionTypeSpecific(printer);
+
+ const string& field_options(variables_.at("fieldoptions"));
+ if (field_options.empty()) {
+ printer->Print(" .fieldOptions = NULL,\n");
+ } else {
+ // Can't use PrintRaw() here to get the #if/#else/#endif lines completely
+ // outdented because the need for indent captured on the previous
+ // printing of a \n and there is no way to get the current indent level
+ // to call the right number of Outdent()/Indents() to maintain state.
+ printer->Print(
+ variables_,
+ "#if GPBOBJC_INCLUDE_FIELD_OPTIONS\n"
+ " .fieldOptions = $fieldoptions$,\n"
+ "#else\n"
+ " .fieldOptions = NULL,\n"
+ "#endif // GPBOBJC_INCLUDE_FIELD_OPTIONS\n");
+ }
+
+ printer->Print("},\n");
+}
+
+void FieldGenerator::GenerateFieldDescriptionTypeSpecific(
+ io::Printer* printer) const {
+ printer->Print(
+ variables_,
+ " .typeSpecific.$typeSpecific_name$ = $typeSpecific_value$,\n");
+}
+
+void FieldGenerator::SetOneofIndexBase(int index_base) {
+ if (descriptor_->containing_oneof() != NULL) {
+ int index = descriptor_->containing_oneof()->index() + index_base;
+ // Flip the sign to mark it as a oneof.
+ variables_["has_index"] = SimpleItoa(-index);;
+ }
+}
+
+void FieldGenerator::FinishInitialization(void) {
+ // Nothing
+}
+
+SingleFieldGenerator::SingleFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : FieldGenerator(descriptor) {
+ // Nothing
+}
+
+SingleFieldGenerator::~SingleFieldGenerator() {}
+
+void SingleFieldGenerator::GenerateFieldStorageDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$storage_type$ $name$;\n");
+}
+
+void SingleFieldGenerator::GeneratePropertyDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$comments$");
+ if (WantsHasProperty()) {
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+ }
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite) $storage_type$ $name$;\n"
+ "\n");
+}
+
+void SingleFieldGenerator::GeneratePropertyImplementation(
+ io::Printer* printer) const {
+ if (WantsHasProperty()) {
+ printer->Print(variables_, "@dynamic has$capitalized_name$, $name$;\n");
+ } else {
+ printer->Print(variables_, "@dynamic $name$;\n");
+ }
+}
+
+bool SingleFieldGenerator::WantsHasProperty(void) const {
+ if (descriptor_->containing_oneof() != NULL) {
+ // If in a oneof, it uses the oneofcase instead of a has bit.
+ return false;
+ }
+ if (HasFieldPresence(descriptor_->file())) {
+ // In proto1/proto2, every field has a has_$name$() method.
+ return true;
+ }
+ return false;
+}
+
+ObjCObjFieldGenerator::ObjCObjFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : SingleFieldGenerator(descriptor) {
+ variables_["property_storage_attribute"] = "strong";
+ if (IsRetainedName(variables_["name"])) {
+ variables_["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
+ }
+}
+
+ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {}
+
+void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$storage_type$ *$name$;\n");
+}
+
+void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
+ io::Printer* printer) const {
+
+ // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
+ // it uses pointers and deals with Objective C's rules around storage name
+ // conventions (init*, new*, etc.)
+
+ printer->Print(variables_, "$comments$");
+ if (WantsHasProperty()) {
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite) BOOL has$capitalized_name$;\n");
+ }
+ printer->Print(
+ variables_,
+ "@property(nonatomic, readwrite, $property_storage_attribute$) $storage_type$ *$name$$storage_attribute$;\n");
+ if (IsInitName(variables_.at("name"))) {
+ // If property name starts with init we need to annotate it to get past ARC.
+ // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+ printer->Print(variables_,
+ "- ($storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+ }
+ printer->Print("\n");
+}
+
+RepeatedFieldGenerator::RepeatedFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : ObjCObjFieldGenerator(descriptor) {
+ // Repeated fields don't use the has index.
+ variables_["has_index"] = "GPBNoHasBit";
+}
+
+RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
+
+void RepeatedFieldGenerator::FinishInitialization(void) {
+ FieldGenerator::FinishInitialization();
+ variables_["array_comment"] =
+ "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+}
+
+void RepeatedFieldGenerator::GenerateFieldStorageDeclaration(
+ io::Printer* printer) const {
+ printer->Print(variables_, "$array_storage_type$ *$name$;\n");
+}
+
+void RepeatedFieldGenerator::GeneratePropertyImplementation(
+ io::Printer* printer) const {
+ printer->Print(variables_, "@dynamic $name$;\n");
+}
+
+void RepeatedFieldGenerator::GeneratePropertyDeclaration(
+ io::Printer* printer) const {
+
+ // Repeated fields don't need the has* properties, but this has the same
+ // logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for dealing
+ // with needing Objective C's rules around storage name conventions (init*,
+ // new*, etc.)
+
+ printer->Print(
+ variables_,
+ "$comments$"
+ "$array_comment$"
+ "@property(nonatomic, readwrite, strong) $array_storage_type$ *$name$$storage_attribute$;\n");
+ if (IsInitName(variables_.at("name"))) {
+ // If property name starts with init we need to annotate it to get past ARC.
+ // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+ printer->Print(variables_,
+ "- ($array_storage_type$ *)$name$ GPB_METHOD_FAMILY_NONE;\n");
+ }
+ printer->Print("\n");
+}
+
+bool RepeatedFieldGenerator::WantsHasProperty(void) const {
+ // Consumer check the array size/existance rather than a has bit.
+ return false;
+}
+
+FieldGeneratorMap::FieldGeneratorMap(const Descriptor* descriptor)
+ : descriptor_(descriptor),
+ field_generators_(
+ new scoped_ptr<FieldGenerator>[descriptor->field_count()]),
+ extension_generators_(
+ new scoped_ptr<FieldGenerator>[descriptor->extension_count()]) {
+ // Construct all the FieldGenerators.
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ field_generators_[i].reset(FieldGenerator::Make(descriptor->field(i)));
+ }
+ for (int i = 0; i < descriptor->extension_count(); i++) {
+ extension_generators_[i].reset(FieldGenerator::Make(descriptor->extension(i)));
+ }
+}
+
+FieldGeneratorMap::~FieldGeneratorMap() {}
+
+const FieldGenerator& FieldGeneratorMap::get(
+ const FieldDescriptor* field) const {
+ GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
+ return *field_generators_[field->index()];
+}
+
+const FieldGenerator& FieldGeneratorMap::get_extension(int index) const {
+ return *extension_generators_[index];
+}
+
+void FieldGeneratorMap::SetOneofIndexBase(int index_base) {
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_[i]->SetOneofIndexBase(index_base);
+ }
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/objectivec_field.h
new file mode 100644
index 00000000..c65e73b2
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_field.h
@@ -0,0 +1,166 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+
+namespace io {
+class Printer; // printer.h
+} // namespace io
+
+namespace compiler {
+namespace objectivec {
+
+class FieldGenerator {
+ public:
+ static FieldGenerator* Make(const FieldDescriptor* field);
+
+ virtual ~FieldGenerator();
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const = 0;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const = 0;
+
+ virtual void GeneratePropertyImplementation(io::Printer* printer) const = 0;
+
+ virtual void GenerateFieldDescription(io::Printer* printer) const;
+ virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+ virtual void GenerateFieldNumberConstant(io::Printer* printer) const;
+
+ virtual void GenerateCFunctionDeclarations(io::Printer* printer) const;
+ virtual void GenerateCFunctionImplementations(io::Printer* printer) const;
+
+ void SetOneofIndexBase(int index_base);
+
+ string variable(const char* key) const {
+ return variables_.find(key)->second;
+ }
+
+ bool needs_textformat_name_support() const {
+ const string& field_flags = variable("fieldflags");
+ return field_flags.find("GPBFieldTextFormatNameCustom") != string::npos;
+ }
+ string generated_objc_name() const { return variable("name"); }
+ string raw_field_name() const { return variable("raw_field_name"); }
+
+ protected:
+ FieldGenerator(const FieldDescriptor* descriptor);
+
+ virtual void FinishInitialization(void);
+ virtual bool WantsHasProperty(void) const = 0;
+
+ const FieldDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
+};
+
+class SingleFieldGenerator : public FieldGenerator {
+ public:
+ virtual ~SingleFieldGenerator();
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+
+ virtual void GeneratePropertyImplementation(io::Printer* printer) const;
+
+ protected:
+ SingleFieldGenerator(const FieldDescriptor* descriptor);
+ virtual bool WantsHasProperty(void) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingleFieldGenerator);
+};
+
+// Subclass with common support for when the field ends up as an ObjC Object.
+class ObjCObjFieldGenerator : public SingleFieldGenerator {
+ public:
+ virtual ~ObjCObjFieldGenerator();
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+
+ protected:
+ ObjCObjFieldGenerator(const FieldDescriptor* descriptor);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjCObjFieldGenerator);
+};
+
+class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
+ public:
+ virtual ~RepeatedFieldGenerator();
+
+ virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const;
+ virtual void GeneratePropertyDeclaration(io::Printer* printer) const;
+
+ virtual void GeneratePropertyImplementation(io::Printer* printer) const;
+
+ protected:
+ RepeatedFieldGenerator(const FieldDescriptor* descriptor);
+ virtual void FinishInitialization(void);
+ virtual bool WantsHasProperty(void) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedFieldGenerator);
+};
+
+// Convenience class which constructs FieldGenerators for a Descriptor.
+class FieldGeneratorMap {
+ public:
+ FieldGeneratorMap(const Descriptor* descriptor);
+ ~FieldGeneratorMap();
+
+ const FieldGenerator& get(const FieldDescriptor* field) const;
+ const FieldGenerator& get_extension(int index) const;
+
+ void SetOneofIndexBase(int index_base);
+
+ private:
+ const Descriptor* descriptor_;
+ scoped_array<scoped_ptr<FieldGenerator> > field_generators_;
+ scoped_array<scoped_ptr<FieldGenerator> > extension_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
+};
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
new file mode 100644
index 00000000..f1e8c0a0
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
@@ -0,0 +1,392 @@
+// 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.
+
+#include <google/protobuf/compiler/objectivec/objectivec_file.h>
+#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
+#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
+#include <google/protobuf/compiler/objectivec/objectivec_message.h>
+#include <google/protobuf/compiler/code_generator.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <sstream>
+
+// This is also found in GPBBootstrap.h, and needs to be kept in sync. It
+// is the version check done to ensure generated code works with the current
+// runtime being used.
+const int32_t GOOGLE_PROTOBUF_OBJC_GEN_VERSION = 30000;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+FileGenerator::FileGenerator(const FileDescriptor *file)
+ : file_(file),
+ root_class_name_(FileClassName(file)),
+ is_filtered_(true),
+ all_extensions_filtered_(true) {
+ for (int i = 0; i < file_->enum_type_count(); i++) {
+ EnumGenerator *generator = new EnumGenerator(file_->enum_type(i));
+ // The enums are exposed via C functions, so they will dead strip if
+ // not used.
+ is_filtered_ &= false;
+ enum_generators_.push_back(generator);
+ }
+ for (int i = 0; i < file_->message_type_count(); i++) {
+ MessageGenerator *generator =
+ new MessageGenerator(root_class_name_, file_->message_type(i));
+ is_filtered_ &= generator->IsFiltered();
+ is_filtered_ &= generator->IsSubContentFiltered();
+ message_generators_.push_back(generator);
+ }
+ for (int i = 0; i < file_->extension_count(); i++) {
+ ExtensionGenerator *generator =
+ new ExtensionGenerator(root_class_name_, file_->extension(i));
+ is_filtered_ &= generator->IsFiltered();
+ all_extensions_filtered_ &= generator->IsFiltered();
+ extension_generators_.push_back(generator);
+ }
+ // If there is nothing in the file we filter it.
+}
+
+FileGenerator::~FileGenerator() {
+ STLDeleteContainerPointers(dependency_generators_.begin(),
+ dependency_generators_.end());
+ STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
+ STLDeleteContainerPointers(message_generators_.begin(),
+ message_generators_.end());
+ STLDeleteContainerPointers(extension_generators_.begin(),
+ extension_generators_.end());
+}
+
+void FileGenerator::GenerateHeader(io::Printer *printer) {
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n",
+ "filename", file_->name());
+
+ printer->Print("#import \"GPBProtocolBuffers.h\"\n\n");
+
+ // Add some verification that the generated code matches the source the
+ // code is being compiled with.
+ printer->Print(
+ "#if GOOGLE_PROTOBUF_OBJC_GEN_VERSION != $protoc_gen_objc_version$\n"
+ "#error This file was generated by a different version of protoc-gen-objc which is incompatible with your Protocol Buffer sources.\n"
+ "#endif\n"
+ "\n",
+ "protoc_gen_objc_version",
+ SimpleItoa(GOOGLE_PROTOBUF_OBJC_GEN_VERSION));
+
+ if (!IsFiltered()) {
+ const vector<FileGenerator *> &dependency_generators =
+ DependencyGenerators();
+ if (dependency_generators.size() > 0) {
+ for (vector<FileGenerator *>::const_iterator iter =
+ dependency_generators.begin();
+ iter != dependency_generators.end(); ++iter) {
+ printer->Print("#import \"$header$.pbobjc.h\"\n",
+ "header", (*iter)->Path());
+ }
+ printer->Print("\n");
+ }
+ }
+
+ printer->Print("CF_EXTERN_C_BEGIN\n\n");
+
+ if (!IsFiltered()) {
+ set<string> dependencies;
+ DetermineDependencies(&dependencies);
+ for (set<string>::const_iterator i(dependencies.begin());
+ i != dependencies.end(); ++i) {
+ printer->Print("$value$;\n", "value", *i);
+ }
+
+ if (dependencies.begin() != dependencies.end()) {
+ printer->Print("\n");
+ }
+ }
+
+ // need to write out all enums first
+ for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
+ iter != enum_generators_.end(); ++iter) {
+ (*iter)->GenerateHeader(printer);
+ }
+
+ for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->GenerateEnumHeader(printer);
+ }
+
+ // For extensions to chain together, the Root gets created even if there
+ // are no extensions. So if the entire file isn't filtered away, output it.
+ if (!IsFiltered()) {
+ printer->Print(
+ "\n"
+ "#pragma mark - $root_class_name$\n"
+ "\n"
+ "@interface $root_class_name$ : GPBRootObject\n"
+ "@end\n\n",
+ "root_class_name", root_class_name_);
+ }
+
+ if (extension_generators_.size() > 0) {
+ // The dynamic methods block is only needed if there are extensions. If
+ // they are all filtered, output the @interface as a comment so there is
+ // something left in the header for anyone that looks.
+ const char *root_line_prefix = "";
+ if (AreAllExtensionsFiltered()) {
+ root_line_prefix = "// ";
+ }
+ printer->Print(
+ "$root_line_prefix$@interface $root_class_name$ (DynamicMethods)\n",
+ "root_class_name", root_class_name_,
+ "root_line_prefix", root_line_prefix);
+
+ for (vector<ExtensionGenerator *>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateMembersHeader(printer);
+ }
+
+ printer->Print("$root_line_prefix$@end\n\n",
+ "root_line_prefix", root_line_prefix);
+ } // extension_generators_.size() > 0
+
+ for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->GenerateMessageHeader(printer);
+ }
+
+ printer->Print("CF_EXTERN_C_END\n");
+}
+
+void DetermineDependenciesWorker(set<string> *dependencies,
+ set<string> *seen_files,
+ const string &classname,
+ const FileDescriptor *file) {
+ if (seen_files->find(file->name()) != seen_files->end()) {
+ // don't infinitely recurse
+ return;
+ }
+
+ seen_files->insert(file->name());
+
+ for (int i = 0; i < file->dependency_count(); i++) {
+ DetermineDependenciesWorker(dependencies, seen_files, classname,
+ file->dependency(i));
+ }
+ for (int i = 0; i < file->message_type_count(); i++) {
+ MessageGenerator(classname, file->message_type(i))
+ .DetermineDependencies(dependencies);
+ }
+}
+
+void FileGenerator::DetermineDependencies(set<string> *dependencies) {
+ set<string> seen_files;
+ DetermineDependenciesWorker(dependencies, &seen_files, root_class_name_,
+ file_);
+}
+
+void FileGenerator::GenerateSource(io::Printer *printer) {
+ printer->Print(
+ "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+ "// source: $filename$\n"
+ "\n",
+ "filename", file_->name());
+
+ if (IsFiltered()) {
+ printer->Print(
+ "// File empty because all messages, extensions and enum have been filtered.\n"
+ "\n"
+ "\n"
+ "// Dummy symbol that will be stripped but will avoid linker warnings about\n"
+ "// no symbols in the .o form compiling this file.\n"
+ "static int $root_class_name$_dummy __attribute__((unused,used)) = 0;\n",
+ "root_class_name", root_class_name_);
+ return;
+ }
+
+ printer->Print("#import \"GPBProtocolBuffers_RuntimeSupport.h\"\n\n");
+
+ string header_file = Path() + ".pbobjc.h";
+
+ printer->Print(
+ "#import \"$header_file$\"\n"
+ "\n"
+ "#pragma mark - $root_class_name$\n"
+ "\n"
+ "@implementation $root_class_name$\n\n",
+ "header_file", header_file,
+ "root_class_name", root_class_name_);
+
+ bool generated_extensions = false;
+ if (file_->extension_count() + file_->message_type_count() +
+ file_->dependency_count() >
+ 0) {
+ ostringstream extensions_stringstream;
+
+ if (file_->extension_count() + file_->message_type_count() > 0) {
+ io::OstreamOutputStream extensions_outputstream(&extensions_stringstream);
+ io::Printer extensions_printer(&extensions_outputstream, '$');
+ extensions_printer.Print(
+ "static GPBExtensionDescription descriptions[] = {\n");
+ extensions_printer.Indent();
+ for (vector<ExtensionGenerator *>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(
+ &extensions_printer, &generated_extensions, true);
+ }
+ for (vector<MessageGenerator *>::iterator iter =
+ message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(&extensions_printer,
+ &generated_extensions);
+ }
+ extensions_printer.Outdent();
+ extensions_printer.Print("};\n");
+ if (generated_extensions) {
+ extensions_printer.Print(
+ "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
+ " GPBExtensionField *extension = [[GPBExtensionField alloc] initWithDescription:&descriptions[i]];\n"
+ " [registry addExtension:extension];\n"
+ " [self globallyRegisterExtension:extension];\n"
+ " [extension release];\n"
+ "}\n");
+ } else {
+ extensions_printer.Print("#pragma unused (descriptions)\n");
+ }
+ const vector<FileGenerator *> &dependency_generators =
+ DependencyGenerators();
+ if (dependency_generators.size()) {
+ for (vector<FileGenerator *>::const_iterator iter =
+ dependency_generators.begin();
+ iter != dependency_generators.end(); ++iter) {
+ if (!(*iter)->IsFiltered()) {
+ extensions_printer.Print(
+ "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
+ "dependency", (*iter)->RootClassName());
+ generated_extensions = true;
+ }
+ }
+ } else if (!generated_extensions) {
+ extensions_printer.Print("#pragma unused (registry)\n");
+ }
+ }
+
+ if (generated_extensions) {
+ printer->Print(
+ "+ (GPBExtensionRegistry*)extensionRegistry {\n"
+ " // This is called by +initialize so there is no need to worry\n"
+ " // about thread safety and initialization of registry.\n"
+ " static GPBExtensionRegistry* registry = nil;\n"
+ " if (!registry) {\n"
+ " registry = [[GPBExtensionRegistry alloc] init];\n");
+
+ printer->Indent();
+ printer->Indent();
+
+ extensions_stringstream.flush();
+ printer->Print(extensions_stringstream.str().c_str());
+ printer->Outdent();
+ printer->Outdent();
+
+ printer->Print(
+ " }\n"
+ " return registry;\n"
+ "}\n"
+ "\n"
+ "+ (void)load {\n"
+ " @autoreleasepool {\n"
+ " [self extensionRegistry]; // Construct extension registry.\n"
+ " }\n"
+ "}\n\n");
+ }
+ }
+
+ printer->Print("@end\n\n");
+
+
+ string syntax;
+ switch (file_->syntax()) {
+ case FileDescriptor::SYNTAX_UNKNOWN:
+ syntax = "GPBFileSyntaxUnknown";
+ break;
+ case FileDescriptor::SYNTAX_PROTO2:
+ syntax = "GPBFileSyntaxProto2";
+ break;
+ case FileDescriptor::SYNTAX_PROTO3:
+ syntax = "GPBFileSyntaxProto3";
+ break;
+ }
+ printer->Print(
+ "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
+ " // This is called by +initialize so there is no need to worry\n"
+ " // about thread safety of the singleton.\n"
+ " static GPBFileDescriptor *descriptor = NULL;\n"
+ " if (!descriptor) {\n"
+ " descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+ " syntax:$syntax$];\n"
+ " }\n"
+ " return descriptor;\n"
+ "}\n"
+ "\n",
+ "root_class_name", root_class_name_,
+ "package", file_->package(),
+ "syntax", syntax);
+
+ for (vector<EnumGenerator *>::iterator iter = enum_generators_.begin();
+ iter != enum_generators_.end(); ++iter) {
+ (*iter)->GenerateSource(printer);
+ }
+ for (vector<MessageGenerator *>::iterator iter = message_generators_.begin();
+ iter != message_generators_.end(); ++iter) {
+ (*iter)->GenerateSource(printer);
+ }
+}
+
+const string FileGenerator::Path() const { return FilePath(file_); }
+
+const vector<FileGenerator *> &FileGenerator::DependencyGenerators() {
+ if (file_->dependency_count() != dependency_generators_.size()) {
+ for (int i = 0; i < file_->dependency_count(); i++) {
+ FileGenerator *generator = new FileGenerator(file_->dependency(i));
+ dependency_generators_.push_back(generator);
+ }
+ }
+ return dependency_generators_;
+}
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
new file mode 100644
index 00000000..fbd08eae
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_file.h
@@ -0,0 +1,94 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+class FileDescriptor; // descriptor.h
+namespace io {
+class Printer; // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class EnumGenerator;
+class ExtensionGenerator;
+class MessageGenerator;
+
+class FileGenerator {
+ public:
+ explicit FileGenerator(const FileDescriptor* file);
+ ~FileGenerator();
+
+ void GenerateSource(io::Printer* printer);
+ void GenerateHeader(io::Printer* printer);
+
+ const string& RootClassName() const { return root_class_name_; }
+ const string Path() const;
+
+ bool IsFiltered() const { return is_filtered_; }
+ bool AreAllExtensionsFiltered() const { return all_extensions_filtered_; }
+
+ private:
+ const FileDescriptor* file_;
+ string root_class_name_;
+
+ // Access this field through the DependencyGenerators accessor call below.
+ // Do not reference it directly.
+ vector<FileGenerator*> dependency_generators_;
+
+ vector<EnumGenerator*> enum_generators_;
+ vector<MessageGenerator*> message_generators_;
+ vector<ExtensionGenerator*> extension_generators_;
+ bool is_filtered_;
+ bool all_extensions_filtered_;
+
+ void DetermineDependencies(set<string>* dependencies);
+
+ const vector<FileGenerator*>& DependencyGenerators();
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
+};
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
new file mode 100644
index 00000000..1eb31a79
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
@@ -0,0 +1,95 @@
+// 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.
+
+#include <iostream>
+#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
+#include <google/protobuf/compiler/objectivec/objectivec_file.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/zero_copy_stream.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+ObjectiveCGenerator::ObjectiveCGenerator() {}
+
+ObjectiveCGenerator::~ObjectiveCGenerator() {}
+
+bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
+ const string& parameter,
+ OutputDirectory* output_directory,
+ string* error) const {
+ // ObjC doesn't have any options at the moment, error if passed one.
+ vector<pair<string, string> > options;
+ ParseGeneratorParameter(parameter, &options);
+ for (int i = 0; i < options.size(); i++) {
+ *error = "error:: Unknown generator option: " + options[i].first;
+ return false;
+ }
+
+ if (!InitializeClassWhitelist(error)) {
+ return false;
+ }
+
+ FileGenerator file_generator(file);
+
+ string filepath = FilePath(file);
+
+ // Generate header.
+ {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->Open(filepath + ".pbobjc.h"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateHeader(&printer);
+ }
+
+ // Generate m file.
+ {
+ scoped_ptr<io::ZeroCopyOutputStream> output(
+ output_directory->Open(filepath + ".pbobjc.m"));
+ io::Printer printer(output.get(), '$');
+ file_generator.GenerateSource(&printer);
+ }
+
+ if (!WriteClassList(error)) {
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
new file mode 100644
index 00000000..24286ac9
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_generator.h
@@ -0,0 +1,60 @@
+// 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.
+
+// Generates ObjectiveC code for a given .proto file.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
+
+#include <string>
+#include <google/protobuf/compiler/code_generator.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class LIBPROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator {
+ public:
+ ObjectiveCGenerator();
+ ~ObjectiveCGenerator();
+
+ // implements CodeGenerator ----------------------------------------
+ bool Generate(const FileDescriptor* file, const string& parameter,
+ OutputDirectory* output_directory, string* error) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectiveCGenerator);
+};
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
new file mode 100644
index 00000000..a4eba09b
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
@@ -0,0 +1,1131 @@
+// 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.
+
+#include <arpa/inet.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <vector>
+
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+#ifndef htonl
+#include <netinet/in.h>
+#endif
+
+#ifndef O_EXLOCK
+#include <sys/file.h>
+#endif
+
+// NOTE: src/google/protobuf/compiler/plugin.cc makes use of cerr for some
+// error case, so it seem to be ok to use as a back door for errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+hash_set<string> gClassWhitelist;
+stringstream gClassListStream;
+
+// islower()/isupper()/tolower()/toupper() change based on locale.
+
+bool IsLower(const char c) {
+ return ('a' <= c && c <= 'z');
+}
+
+bool IsUpper(const char c) {
+ return ('A' <= c && c <= 'Z');
+}
+
+char ToLower(char c) {
+ if ('A' <= c && c <= 'Z') {
+ c += 'a' - 'A';
+ }
+ return c;
+}
+
+// toupper() changes based on locale. We don't want this!
+char ToUpper(char c) {
+ if ('a' <= c && c <= 'z') {
+ c += 'A' - 'a';
+ }
+ return c;
+}
+
+string TrimString(const string& s) {
+ string::size_type start = s.find_first_not_of(" \n\r\t");
+ if (start == string::npos) {
+ return "";
+ }
+ string::size_type end = s.find_last_not_of(" \n\r\t") + 1;
+ return s.substr(start, end - start);
+}
+
+hash_set<string> MakeWordsMap(const char* const words[], size_t num_words) {
+ hash_set<string> result;
+ for (int i = 0; i < num_words; i++) {
+ result.insert(words[i]);
+ }
+ return result;
+}
+
+const char* const kUpperSegmentsList[] = {"url", "http", "https"};
+
+hash_set<string> kUpperSegments =
+ MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList));
+
+// Internal helper for name handing.
+// Do not expose this outside of helpers, stick to having functions for specific
+// cases (ClassName(), FieldName()), so there is always consistent suffix rules.
+string UnderscoresToCamelCase(const string& input, bool first_capitalized) {
+ vector<string> values;
+ string current;
+
+ bool last_char_was_number = false;
+ bool last_char_was_lower = false;
+ bool last_char_was_upper = false;
+ for (int i = 0; i < input.size(); i++) {
+ char c = input[i];
+ if (c >= '0' && c <= '9') {
+ if (!last_char_was_number) {
+ values.push_back(current);
+ current = "";
+ }
+ current += c;
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ last_char_was_number = true;
+ } else if (IsLower(c)) {
+ // lowercase letter can follow a lowercase or uppercase letter
+ if (!last_char_was_lower && !last_char_was_upper) {
+ values.push_back(current);
+ current = "";
+ }
+ current += c; // already lower
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ last_char_was_lower = true;
+ } else if (IsUpper(c)) {
+ if (!last_char_was_upper) {
+ values.push_back(current);
+ current = "";
+ }
+ current += ToLower(c);
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ last_char_was_upper = true;
+ } else {
+ last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+ }
+ }
+ values.push_back(current);
+
+ for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
+ string value = *i;
+ bool all_upper = (kUpperSegments.count(value) > 0);
+ for (int j = 0; j < value.length(); j++) {
+ if (j == 0 || all_upper) {
+ value[j] = ToUpper(value[j]);
+ } else {
+ // Nothing, already in lower.
+ }
+ }
+ *i = value;
+ }
+ string result;
+ for (vector<string>::iterator i = values.begin(); i != values.end(); ++i) {
+ result += *i;
+ }
+ if ((result.length() != 0) && !first_capitalized) {
+ result[0] = ToLower(result[0]);
+ }
+ return result;
+}
+
+const char* const kReservedWordList[] = {
+ // Objective C "keywords" that aren't in C
+ // From
+ // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
+ "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway",
+ "self",
+
+ // C/C++ keywords (Incl C++ 0x11)
+ // From http://en.cppreference.com/w/cpp/keywords
+ "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor",
+ "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class",
+ "compl", "const", "constexpr", "const_cast", "continue", "decltype",
+ "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit",
+ "export", "extern ", "false", "float", "for", "friend", "goto", "if",
+ "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not",
+ "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected",
+ "public", "register", "reinterpret_cast", "return", "short", "signed",
+ "sizeof", "static", "static_assert", "static_cast", "struct", "switch",
+ "template", "this", "thread_local", "throw", "true", "try", "typedef",
+ "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
+ "volatile", "wchar_t", "while", "xor", "xor_eq",
+
+ // C99 keywords
+ // From
+ // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
+ "restrict",
+
+ // Objective-C Runtime typedefs
+ // From <obc/runtime.h>
+ "Category", "Ivar", "Method", "Protocol",
+
+ // NSObject Methods
+ // new is covered by C++ keywords.
+ "description", "debugDescription", "finalize", "hash", "dealloc", "init",
+ "class", "superclass", "retain", "release", "autorelease", "retainCount",
+ "zone", "isProxy", "copy", "mutableCopy", "classForCoder",
+
+ // GPBMessage Methods
+ // Only need to add instance methods that may conflict with
+ // method declared in protos. The main cases are methods
+ // that take no arguments, or setFoo:/hasFoo: type methods.
+ // These are currently in the same order as in GPBMessage.h.
+ "unknownFields", "extensionRegistry", "isInitialized",
+ "data", "delimitedData", "serializedSize",
+ "descriptor", "extensionsCurrentlySet", "clear", "sortedExtensionsInUse",
+
+ // MacTypes.h names
+ "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount",
+ "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount",
+ "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType",
+ "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style",
+ "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord",
+};
+
+hash_set<string> kReservedWords =
+ MakeWordsMap(kReservedWordList, GOOGLE_ARRAYSIZE(kReservedWordList));
+
+string SanitizeNameForObjC(const string& input, const string& extension) {
+ if (kReservedWords.count(input) > 0) {
+ return input + extension;
+ }
+ return input;
+}
+
+string NameFromFieldDescriptor(const FieldDescriptor* field) {
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ return field->message_type()->name();
+ } else {
+ return field->name();
+ }
+}
+
+// Escape C++ trigraphs by escaping question marks to \?
+string EscapeTrigraphs(const string& to_escape) {
+ return StringReplace(to_escape, "?", "\\?", true);
+}
+
+void PathSplit(const string& path, string* directory, string* basename) {
+ string::size_type last_slash = path.rfind('/');
+ if (last_slash == string::npos) {
+ if (directory) {
+ *directory = "";
+ }
+ if (basename) {
+ *basename = path;
+ }
+ } else {
+ if (directory) {
+ *directory = path.substr(0, last_slash);
+ }
+ if (basename) {
+ *basename = path.substr(last_slash + 1);
+ }
+ }
+}
+
+bool IsSpecialName(const string& name, const string* special_names,
+ size_t count) {
+ for (size_t i = 0; i < count; ++i) {
+ size_t length = special_names[i].length();
+ if (name.compare(0, length, special_names[i]) == 0) {
+ if (name.length() > length) {
+ // If name is longer than the retained_name[i] that it matches
+ // the next character must be not lower case (newton vs newTon vs
+ // new_ton).
+ return !IsLower(name[length]);
+ } else {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+} // namespace
+
+string StripProto(const string& filename) {
+ if (HasSuffixString(filename, ".protodevel")) {
+ return StripSuffixString(filename, ".protodevel");
+ } else {
+ return StripSuffixString(filename, ".proto");
+ }
+}
+
+bool IsRetainedName(const string& name) {
+ // List of prefixes from
+ // http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
+ static const string retained_names[] = {"new", "alloc", "copy",
+ "mutableCopy"};
+ return IsSpecialName(name, retained_names,
+ sizeof(retained_names) / sizeof(retained_names[0]));
+}
+
+bool IsInitName(const string& name) {
+ static const string init_names[] = {"init"};
+ return IsSpecialName(name, init_names,
+ sizeof(init_names) / sizeof(init_names[0]));
+}
+
+string BaseFileName(const FileDescriptor* file) {
+ string basename;
+ PathSplit(file->name(), NULL, &basename);
+ return basename;
+}
+
+string FileName(const FileDescriptor* file) {
+ string path = FilePath(file);
+ string basename;
+ PathSplit(path, NULL, &basename);
+ return basename;
+}
+
+string FilePath(const FileDescriptor* file) {
+ string output;
+ string basename;
+ string directory;
+ PathSplit(file->name(), &directory, &basename);
+ if (directory.length() > 0) {
+ output = directory + "/";
+ }
+ basename = StripProto(basename);
+
+ // CamelCase to be more ObjC friendly.
+ basename = UnderscoresToCamelCase(basename, true);
+
+ output += basename;
+ return output;
+}
+
+string FileClassPrefix(const FileDescriptor* file) {
+ // Default is empty string, no need to check has_objc_class_prefix.
+ return file->options().objc_class_prefix();
+}
+
+string FileClassName(const FileDescriptor* file) {
+ string name = FileClassPrefix(file);
+ name += UnderscoresToCamelCase(StripProto(BaseFileName(file)), true);
+ name += "Root";
+ // There aren't really any reserved words that end in "Root", but playing
+ // it safe and checking.
+ return SanitizeNameForObjC(name, "_RootClass");
+}
+
+string ClassNameWorker(const Descriptor* descriptor) {
+ string name;
+ if (descriptor->containing_type() != NULL) {
+ name = ClassNameWorker(descriptor->containing_type());
+ name += "_";
+ }
+ return name + descriptor->name();
+}
+
+string ClassNameWorker(const EnumDescriptor* descriptor) {
+ string name;
+ if (descriptor->containing_type() != NULL) {
+ name = ClassNameWorker(descriptor->containing_type());
+ name += "_";
+ }
+ return name + descriptor->name();
+}
+
+string ClassName(const Descriptor* descriptor) {
+ // 1. Message names are used as is (style calls for CamelCase, trust it).
+ // 2. Check for reserved word at the very end and then suffix things.
+ string prefix = FileClassPrefix(descriptor->file());
+ string name = ClassNameWorker(descriptor);
+ return SanitizeNameForObjC(prefix + name, "_Class");
+}
+
+string EnumName(const EnumDescriptor* descriptor) {
+ // 1. Enum names are used as is (style calls for CamelCase, trust it).
+ // 2. Check for reserved word at the every end and then suffix things.
+ // message Fixed {
+ // message Size {...}
+ // enum Mumble {...}
+ // ...
+ // }
+ // yields Fixed_Class, Fixed_Size.
+ string name = FileClassPrefix(descriptor->file());
+ name += ClassNameWorker(descriptor);
+ return SanitizeNameForObjC(name, "_Enum");
+}
+
+string EnumValueName(const EnumValueDescriptor* descriptor) {
+ // Because of the Switch enum compatibility, the name on the enum has to have
+ // the suffix handing, so it slightly diverges from how nested classes work.
+ // enum Fixed {
+ // FOO = 1
+ // }
+ // yields Fixed_Enum and Fixed_Enum_Foo (not Fixed_Foo).
+ const string& class_name = EnumName(descriptor->type());
+ const string& value_str = UnderscoresToCamelCase(descriptor->name(), true);
+ const string& name = class_name + "_" + value_str;
+ // There aren't really any reserved words with an underscore and a leading
+ // capital letter, but playing it safe and checking.
+ return SanitizeNameForObjC(name, "_Value");
+}
+
+string EnumValueShortName(const EnumValueDescriptor* descriptor) {
+ // Enum value names (EnumValueName above) are the enum name turned into
+ // a class name and then the value name is CamelCased and concatenated; the
+ // whole thing then gets sanitized for reserved words.
+ // The "short name" is intended to be the final leaf, the value name; but
+ // you can't simply send that off to sanitize as that could result in it
+ // getting modified when the full name didn't. For example enum
+ // "StorageModes" has a value "retain". So the full name is
+ // "StorageModes_Retain", but if we sanitize "retain" it would become
+ // "RetainValue".
+ // So the right way to get the short name is to take the full enum name
+ // and then strip off the enum name (leaving the value name and anything
+ // done by sanitize).
+ const string& class_name = EnumName(descriptor->type());
+ const string& long_name_prefix = class_name + "_";
+ const string& long_name = EnumValueName(descriptor);
+ return StripPrefixString(long_name, long_name_prefix);
+}
+
+string UnCamelCaseEnumShortName(const string& name) {
+ string result;
+ for (int i = 0; i < name.size(); i++) {
+ char c = name[i];
+ if (i > 0 && c >= 'A' && c <= 'Z') {
+ result += '_';
+ }
+ result += ToUpper(c);
+ }
+ return result;
+}
+
+string ExtensionMethodName(const FieldDescriptor* descriptor) {
+ const string& name = NameFromFieldDescriptor(descriptor);
+ const string& result = UnderscoresToCamelCase(name, false);
+ return SanitizeNameForObjC(result, "_Extension");
+}
+
+string FieldName(const FieldDescriptor* field) {
+ const string& name = NameFromFieldDescriptor(field);
+ string result = UnderscoresToCamelCase(name, false);
+ if (field->is_repeated() && !field->is_map()) {
+ // Add "Array" before do check for reserved worlds.
+ result += "Array";
+ } else {
+ // If it wasn't repeated, but ends in "Array", force on the _p suffix.
+ if (HasSuffixString(result, "Array")) {
+ result += "_p";
+ }
+ }
+ return SanitizeNameForObjC(result, "_p");
+}
+
+string FieldNameCapitalized(const FieldDescriptor* field) {
+ // Want the same suffix handling, so upcase the first letter of the other
+ // name.
+ string result = FieldName(field);
+ if (result.length() > 0) {
+ result[0] = ToUpper(result[0]);
+ }
+ return result;
+}
+
+string OneofEnumName(const OneofDescriptor* descriptor) {
+ const Descriptor* fieldDescriptor = descriptor->containing_type();
+ string name = ClassName(fieldDescriptor);
+ name += "_" + UnderscoresToCamelCase(descriptor->name(), true) + "_OneOfCase";
+ // No sanitize needed because it the OS never has names that end in OneOfCase.
+ return name;
+}
+
+string OneofName(const OneofDescriptor* descriptor) {
+ string name = UnderscoresToCamelCase(descriptor->name(), false);
+ // No sanitize needed because it gets OneOfCase added and that shouldn't
+ // ever conflict.
+ return name;
+}
+
+string OneofNameCapitalized(const OneofDescriptor* descriptor) {
+ // Use the common handling and then up-case the first letter.
+ string result = OneofName(descriptor);
+ if (result.length() > 0) {
+ result[0] = ToUpper(result[0]);
+ }
+ return result;
+}
+
+string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field) {
+ string worker(name);
+ if (HasSuffixString(worker, "_p")) {
+ worker = StripSuffixString(worker, "_p");
+ }
+ if (field->is_repeated() && HasSuffixString(worker, "Array")) {
+ worker = StripSuffixString(worker, "Array");
+ }
+ if (field->type() == FieldDescriptor::TYPE_GROUP) {
+ if (worker.length() > 0) {
+ if (worker[0] >= 'a' && worker[0] <= 'z') {
+ worker[0] = ToUpper(worker[0]);
+ }
+ }
+ return worker;
+ } else {
+ string result;
+ for (int i = 0; i < worker.size(); i++) {
+ char c = worker[i];
+ if (c >= 'A' && c <= 'Z') {
+ if (i > 0) {
+ result += '_';
+ }
+ result += ToLower(c);
+ } else {
+ result += c;
+ }
+ }
+ return result;
+ }
+}
+
+string GetCapitalizedType(const FieldDescriptor* field) {
+ switch (field->type()) {
+ case FieldDescriptor::TYPE_INT32:
+ return "Int32";
+ case FieldDescriptor::TYPE_UINT32:
+ return "UInt32";
+ case FieldDescriptor::TYPE_SINT32:
+ return "SInt32";
+ case FieldDescriptor::TYPE_FIXED32:
+ return "Fixed32";
+ case FieldDescriptor::TYPE_SFIXED32:
+ return "SFixed32";
+ case FieldDescriptor::TYPE_INT64:
+ return "Int64";
+ case FieldDescriptor::TYPE_UINT64:
+ return "UInt64";
+ case FieldDescriptor::TYPE_SINT64:
+ return "SInt64";
+ case FieldDescriptor::TYPE_FIXED64:
+ return "Fixed64";
+ case FieldDescriptor::TYPE_SFIXED64:
+ return "SFixed64";
+ case FieldDescriptor::TYPE_FLOAT:
+ return "Float";
+ case FieldDescriptor::TYPE_DOUBLE:
+ return "Double";
+ case FieldDescriptor::TYPE_BOOL:
+ return "Bool";
+ case FieldDescriptor::TYPE_STRING:
+ return "String";
+ case FieldDescriptor::TYPE_BYTES:
+ return "Data";
+ case FieldDescriptor::TYPE_ENUM:
+ return "Enum";
+ case FieldDescriptor::TYPE_GROUP:
+ return "Group";
+ case FieldDescriptor::TYPE_MESSAGE:
+ return "Message";
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) {
+ switch (field_type) {
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ return OBJECTIVECTYPE_INT32;
+
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_FIXED32:
+ return OBJECTIVECTYPE_UINT32;
+
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ return OBJECTIVECTYPE_INT64;
+
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_FIXED64:
+ return OBJECTIVECTYPE_UINT64;
+
+ case FieldDescriptor::TYPE_FLOAT:
+ return OBJECTIVECTYPE_FLOAT;
+
+ case FieldDescriptor::TYPE_DOUBLE:
+ return OBJECTIVECTYPE_DOUBLE;
+
+ case FieldDescriptor::TYPE_BOOL:
+ return OBJECTIVECTYPE_BOOLEAN;
+
+ case FieldDescriptor::TYPE_STRING:
+ return OBJECTIVECTYPE_STRING;
+
+ case FieldDescriptor::TYPE_BYTES:
+ return OBJECTIVECTYPE_DATA;
+
+ case FieldDescriptor::TYPE_ENUM:
+ return OBJECTIVECTYPE_ENUM;
+
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ return OBJECTIVECTYPE_MESSAGE;
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return OBJECTIVECTYPE_INT32;
+}
+
+bool IsPrimitiveType(const FieldDescriptor* field) {
+ ObjectiveCType type = GetObjectiveCType(field);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ case OBJECTIVECTYPE_UINT32:
+ case OBJECTIVECTYPE_INT64:
+ case OBJECTIVECTYPE_UINT64:
+ case OBJECTIVECTYPE_FLOAT:
+ case OBJECTIVECTYPE_DOUBLE:
+ case OBJECTIVECTYPE_BOOLEAN:
+ case OBJECTIVECTYPE_ENUM:
+ return true;
+ break;
+ default:
+ return false;
+ }
+}
+
+bool IsReferenceType(const FieldDescriptor* field) {
+ return !IsPrimitiveType(field);
+}
+
+static string HandleExtremeFloatingPoint(string val, bool add_float_suffix) {
+ if (val == "nan") {
+ return "NAN";
+ } else if (val == "inf") {
+ return "INFINITY";
+ } else if (val == "-inf") {
+ return "-INFINITY";
+ } else {
+ // float strings with ., e or E need to have f appended
+ if (add_float_suffix &&
+ (val.find(".") != string::npos || val.find("e") != string::npos ||
+ val.find("E") != string::npos)) {
+ val += "f";
+ }
+ return val;
+ }
+}
+
+string GPBValueFieldName(const FieldDescriptor* field) {
+ // Returns the field within the GPBValue union to use for the given field.
+ if (field->is_repeated()) {
+ return "valueMessage";
+ }
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ return "valueInt32";
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return "valueUInt32";
+ case FieldDescriptor::CPPTYPE_INT64:
+ return "valueInt64";
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return "valueUInt64";
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return "valueFloat";
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return "valueDouble";
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return "valueBool";
+ case FieldDescriptor::CPPTYPE_STRING:
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ return "valueData";
+ } else {
+ return "valueString";
+ }
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return "valueEnum";
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "valueMessage";
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+
+string DefaultValue(const FieldDescriptor* field) {
+ // Repeated fields don't have defaults.
+ if (field->is_repeated()) {
+ return "nil";
+ }
+
+ // Switch on cpp_type since we need to know which default_value_* method
+ // of FieldDescriptor to call.
+ switch (field->cpp_type()) {
+ case FieldDescriptor::CPPTYPE_INT32:
+ // gcc and llvm reject the decimal form of kint32min and kint64min.
+ if (field->default_value_int32() == INT_MIN) {
+ return "-0x80000000";
+ }
+ return SimpleItoa(field->default_value_int32());
+ case FieldDescriptor::CPPTYPE_UINT32:
+ return SimpleItoa(field->default_value_uint32()) + "U";
+ case FieldDescriptor::CPPTYPE_INT64:
+ // gcc and llvm reject the decimal form of kint32min and kint64min.
+ if (field->default_value_int64() == LLONG_MIN) {
+ return "-0x8000000000000000LL";
+ }
+ return SimpleItoa(field->default_value_int64()) + "LL";
+ case FieldDescriptor::CPPTYPE_UINT64:
+ return SimpleItoa(field->default_value_uint64()) + "ULL";
+ case FieldDescriptor::CPPTYPE_DOUBLE:
+ return HandleExtremeFloatingPoint(
+ SimpleDtoa(field->default_value_double()), false);
+ case FieldDescriptor::CPPTYPE_FLOAT:
+ return HandleExtremeFloatingPoint(
+ SimpleFtoa(field->default_value_float()), true);
+ case FieldDescriptor::CPPTYPE_BOOL:
+ return field->default_value_bool() ? "YES" : "NO";
+ case FieldDescriptor::CPPTYPE_STRING: {
+ const bool has_default_value = field->has_default_value();
+ const string& default_string = field->default_value_string();
+ if (!has_default_value || default_string.length() == 0) {
+ // If the field is defined as being the empty string,
+ // then we will just assign to nil, as the empty string is the
+ // default for both strings and data.
+ return "nil";
+ }
+ if (field->type() == FieldDescriptor::TYPE_BYTES) {
+ // We want constant fields in our data structures so we can
+ // declare them as static. To achieve this we cheat and stuff
+ // a escaped c string (prefixed with a length) into the data
+ // field, and cast it to an (NSData*) so it will compile.
+ // The runtime library knows how to handle it.
+
+ // Must convert to a standard byte order for packing length into
+ // a cstring.
+ uint32_t length = htonl(default_string.length());
+ string bytes((const char*)&length, sizeof(length));
+ bytes.append(default_string);
+ return "(NSData*)\"" + CEscape(bytes) + "\"";
+ } else {
+ return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\"";
+ }
+ }
+ case FieldDescriptor::CPPTYPE_ENUM:
+ return EnumValueName(field->default_value_enum());
+ case FieldDescriptor::CPPTYPE_MESSAGE:
+ return "nil";
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+string BuildFlagsString(const vector<string>& strings) {
+ if (strings.size() == 0) {
+ return "0";
+ }
+ string string;
+ for (size_t i = 0; i != strings.size(); ++i) {
+ if (i > 0) {
+ string.append(" | ");
+ }
+ string.append(strings[i]);
+ }
+ return string;
+}
+
+string BuildCommentsString(const SourceLocation& location) {
+ const string& comments = location.leading_comments.empty()
+ ? location.trailing_comments
+ : location.leading_comments;
+ vector<string> lines;
+ SplitStringAllowEmpty(comments, "\n", &lines);
+ while (!lines.empty() && lines.back().empty()) {
+ lines.pop_back();
+ }
+ string prefix("//");
+ string suffix("\n");
+ string final_comments;
+ for (int i = 0; i < lines.size(); i++) {
+ // We use $ for delimiters, so replace comments with dollars with
+ // html escaped version.
+ // None of the other compilers handle this (as of this writing) but we
+ // ran into it once, so just to be safe.
+ final_comments +=
+ prefix + StringReplace(lines[i], "$", "&#36;", true) + suffix;
+ }
+ return final_comments;
+}
+
+bool WriteClassList(string* error) {
+ const char* file_name = getenv("GPB_CLASSLIST_PATH");
+ if (file_name != NULL) {
+#ifndef O_EXLOCK
+ int fd = open(file_name, O_WRONLY | O_APPEND | O_CREAT,
+ (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
+#else
+ int fd = open(file_name, O_WRONLY | O_APPEND | O_EXLOCK | O_CREAT,
+ (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH));
+#endif
+ if (fd == -1) {
+ if (error != NULL) {
+ stringstream err_stream;
+ err_stream << endl << file_name << ":0:0: error:"
+ << "Unable to open (" << errno << ")";
+ *error = err_stream.str();
+ }
+ return false;
+ }
+#ifndef O_EXLOCK
+ if (flock(fd, LOCK_EX) < 0) {
+ if (error != NULL) {
+ stringstream err_stream;
+ err_stream << endl << file_name << ":0:0: error:"
+ << "Unable to lock (" << errno << ")";
+ *error = err_stream.str();
+ }
+ return false;
+ }
+#endif
+ // Need a local to hold the list so the cstring stays valid for the
+ // write call.
+ const string& class_list_str = gClassListStream.str();
+ int write_out = write(fd, class_list_str.c_str(), class_list_str.length());
+ int close_out = close(fd);
+ if (write_out == -1 || close_out == -1) {
+ if (error != NULL) {
+ stringstream err_stream;
+ err_stream << endl << file_name << ":0:0: error:"
+ << "Unable to write (" << errno << ")";
+ *error = err_stream.str();
+ }
+ return false;
+ }
+ }
+ return true;
+}
+
+void WriteClassNameToClassList(const string& name) {
+ if (gClassListStream.good()) {
+ gClassListStream << name << '\n';
+ }
+}
+
+bool InitializeClassWhitelist(string* error) {
+ const char* env_var_value = getenv("GPB_OBJC_CLASS_WHITELIST_PATHS");
+ if (env_var_value == NULL) {
+ return true;
+ }
+
+ // The values are joined with ';' in case we ever want to make this a
+ // generator parameter also (instead of env var), and generator parameter
+ // parsing already has meaning for ',' and ':'.
+ vector<string> file_paths = Split(env_var_value, ";", true);
+
+ for (vector<string>::const_iterator i = file_paths.begin();
+ i != file_paths.end(); ++i) {
+ const string& file_path = *i;
+
+ ifstream stream(file_path.c_str(), ifstream::in);
+ if (!stream.good()) {
+ if (error != NULL) {
+ stringstream err_stream;
+ err_stream << endl << file_path << ":0:0: error: Unable to open";
+ *error = err_stream.str();
+ return false;
+ }
+ }
+
+ string input_line;
+ while (stream.good()) {
+ getline(stream, input_line);
+ string trimmed_line(TrimString(input_line));
+ if (trimmed_line.length() == 0) {
+ // Skip empty lines
+ continue;
+ }
+ if (trimmed_line[0] == '/' || trimmed_line[0] == '#') {
+ // Skip comments and potential preprocessor symbols
+ continue;
+ }
+ gClassWhitelist.insert(trimmed_line);
+ }
+ }
+ return true;
+}
+
+bool FilterClass(const string& name) {
+ if (gClassWhitelist.count(name) > 0) {
+ // Whitelisted, don't filter.
+ return false;
+ }
+
+ // If there was no list, default to everything in.
+ // If there was a list, default to everything out.
+ return gClassWhitelist.size() > 0;
+}
+
+void TextFormatDecodeData::AddString(int32_t key,
+ const string& input_for_decode,
+ const string& desired_output) {
+ for (vector<DataEntry>::const_iterator i = entries_.begin();
+ i != entries_.end(); ++i) {
+ if (i->first == key) {
+ cerr << "error: duplicate key (" << key
+ << ") making TextFormat data, input: \"" << input_for_decode
+ << "\", desired: \"" << desired_output << "\"." << endl;
+ cerr.flush();
+ abort();
+ }
+ }
+
+ const string& data = TextFormatDecodeData::DecodeDataForString(
+ input_for_decode, desired_output);
+ entries_.push_back(DataEntry(key, data));
+}
+
+string TextFormatDecodeData::Data() const {
+ ostringstream data_stringstream;
+
+ if (num_entries() > 0) {
+ io::OstreamOutputStream data_outputstream(&data_stringstream);
+ io::CodedOutputStream output_stream(&data_outputstream);
+
+ output_stream.WriteVarint32(num_entries());
+ for (vector<DataEntry>::const_iterator i = entries_.begin();
+ i != entries_.end(); ++i) {
+ output_stream.WriteVarint32(i->first);
+ output_stream.WriteString(i->second);
+ }
+ }
+
+ data_stringstream.flush();
+ return data_stringstream.str();
+}
+
+namespace {
+
+// Helper to build up the decode data for a string.
+class DecodeDataBuilder {
+ public:
+ DecodeDataBuilder() { Reset(); }
+
+ bool AddCharacter(const char desired, const char input);
+ void AddUnderscore() {
+ Push();
+ need_underscore_ = true;
+ }
+ string Finish() {
+ Push();
+ return decode_data_;
+ }
+
+ private:
+ static const uint8_t kAddUnderscore = 0b10000000;
+
+ static const uint8_t kOpAsIs = 0b00000000;
+ static const uint8_t kOpFirstUpper = 0b01000000;
+ static const uint8_t kOpFirstLower = 0b00100000;
+ static const uint8_t kOpAllUpper = 0b01100000;
+
+ static const int kMaxSegmentLen = 0b00011111;
+
+ void AddChar(const char desired) {
+ ++segment_len_;
+ is_all_upper_ &= IsUpper(desired);
+ }
+
+ void Push() {
+ uint8_t op = (op_ | segment_len_);
+ if (need_underscore_) op |= kAddUnderscore;
+ if (op != 0) {
+ decode_data_ += (char)op;
+ }
+ Reset();
+ }
+
+ bool AddFirst(const char desired, const char input) {
+ if (desired == input) {
+ op_ = kOpAsIs;
+ } else if (desired == ToUpper(input)) {
+ op_ = kOpFirstUpper;
+ } else if (desired == ToLower(input)) {
+ op_ = kOpFirstLower;
+ } else {
+ // Can't be transformed to match.
+ return false;
+ }
+ AddChar(desired);
+ return true;
+ }
+
+ void Reset() {
+ need_underscore_ = false;
+ op_ = 0;
+ segment_len_ = 0;
+ is_all_upper_ = true;
+ }
+
+ bool need_underscore_;
+ bool is_all_upper_;
+ uint8_t op_;
+ int segment_len_;
+
+ string decode_data_;
+};
+
+bool DecodeDataBuilder::AddCharacter(const char desired, const char input) {
+ // If we've hit the max size, push to start a new segment.
+ if (segment_len_ == kMaxSegmentLen) {
+ Push();
+ }
+ if (segment_len_ == 0) {
+ return AddFirst(desired, input);
+ }
+
+ // Desired and input match...
+ if (desired == input) {
+ // If we aren't transforming it, or we're upper casing it and it is
+ // supposed to be uppercase; just add it to the segment.
+ if ((op_ != kOpAllUpper) || IsUpper(desired)) {
+ AddChar(desired);
+ return true;
+ }
+
+ // Add the current segment, and start the next one.
+ Push();
+ return AddFirst(desired, input);
+ }
+
+ // If we need to uppercase, and everything so far has been uppercase,
+ // promote op to AllUpper.
+ if ((desired == ToUpper(input)) && is_all_upper_) {
+ op_ = kOpAllUpper;
+ AddChar(desired);
+ return true;
+ }
+
+ // Give up, push and start a new segment.
+ Push();
+ return AddFirst(desired, input);
+}
+
+// If decode data can't be generated, a directive for the raw string
+// is used instead.
+string DirectDecodeString(const string& str) {
+ string result;
+ result += (char)'\0'; // Marker for full string.
+ result += str;
+ result += (char)'\0'; // End of string.
+ return result;
+}
+
+} // namespace
+
+// static
+string TextFormatDecodeData::DecodeDataForString(const string& input_for_decode,
+ const string& desired_output) {
+ if ((input_for_decode.size() == 0) || (desired_output.size() == 0)) {
+ cerr << "error: got empty string for making TextFormat data, input: \""
+ << input_for_decode << "\", desired: \"" << desired_output << "\"."
+ << endl;
+ cerr.flush();
+ abort();
+ }
+ if ((input_for_decode.find('\0') != string::npos) ||
+ (desired_output.find('\0') != string::npos)) {
+ cerr << "error: got a null char in a string for making TextFormat data,"
+ << " input: \"" << CEscape(input_for_decode) << "\", desired: \""
+ << CEscape(desired_output) << "\"." << endl;
+ cerr.flush();
+ abort();
+ }
+
+ DecodeDataBuilder builder;
+
+ // Walk the output building it from the input.
+ int x = 0;
+ for (int y = 0; y < desired_output.size(); y++) {
+ const char d = desired_output[y];
+ if (d == '_') {
+ builder.AddUnderscore();
+ continue;
+ }
+
+ if (x >= input_for_decode.size()) {
+ // Out of input, no way to encode it, just return a full decode.
+ return DirectDecodeString(desired_output);
+ }
+ if (builder.AddCharacter(d, input_for_decode[x])) {
+ ++x; // Consumed one input
+ } else {
+ // Couldn't transform for the next character, just return a full decode.
+ return DirectDecodeString(desired_output);
+ }
+ }
+
+ if (x != input_for_decode.size()) {
+ // Extra input (suffix from name sanitizing?), just return a full decode.
+ return DirectDecodeString(desired_output);
+ }
+
+ // Add the end marker.
+ return builder.Finish() + (char)'\0';
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
new file mode 100644
index 00000000..2701a30c
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
@@ -0,0 +1,176 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
+
+#include <string>
+#include <vector>
+
+#include <google/protobuf/descriptor.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// Strips ".proto" or ".protodevel" from the end of a filename.
+string StripProto(const string& filename);
+
+// Returns true if the name requires a ns_returns_not_retained attribute applied
+// to it.
+bool IsRetainedName(const string& name);
+
+// Returns true if the name starts with "init" and will need to have special
+// handling under ARC.
+bool IsInitName(const string& name);
+
+// Gets the name of the file we're going to generate (sans the .pb.h
+// extension). This does not include the path to that file.
+string FileName(const FileDescriptor* file);
+
+// Gets the path of the file we're going to generate (sans the .pb.h
+// extension). The path will be dependent on the objectivec package
+// declared in the proto package.
+string FilePath(const FileDescriptor* file);
+
+// Gets the name of the root class we'll generate in the file. This class
+// is not meant for external consumption, but instead contains helpers that
+// the rest of the the classes need
+string FileClassName(const FileDescriptor* file);
+
+// These return the fully-qualified class name corresponding to the given
+// descriptor.
+string ClassName(const Descriptor* descriptor);
+string EnumName(const EnumDescriptor* descriptor);
+
+// Returns the fully-qualified name of the enum value corresponding to the
+// the descriptor.
+string EnumValueName(const EnumValueDescriptor* descriptor);
+
+// Returns the name of the enum value corresponding to the descriptor.
+string EnumValueShortName(const EnumValueDescriptor* descriptor);
+
+// Reverse what an enum does.
+string UnCamelCaseEnumShortName(const string& name);
+
+// Returns the name to use for the extension (used as the method off the file's
+// Root class).
+string ExtensionMethodName(const FieldDescriptor* descriptor);
+
+// Returns the transformed field name.
+string FieldName(const FieldDescriptor* field);
+string FieldNameCapitalized(const FieldDescriptor* field);
+
+// Returns the transformed oneof name.
+string OneofEnumName(const OneofDescriptor* descriptor);
+string OneofName(const OneofDescriptor* descriptor);
+string OneofNameCapitalized(const OneofDescriptor* descriptor);
+
+inline bool HasFieldPresence(const FileDescriptor* file) {
+ return file->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
+ return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+inline bool IsMapEntryMessage(const Descriptor* descriptor) {
+ return descriptor->options().map_entry();
+}
+
+// Reverse of the above.
+string UnCamelCaseFieldName(const string& name, const FieldDescriptor* field);
+
+enum ObjectiveCType {
+ OBJECTIVECTYPE_INT32,
+ OBJECTIVECTYPE_UINT32,
+ OBJECTIVECTYPE_INT64,
+ OBJECTIVECTYPE_UINT64,
+ OBJECTIVECTYPE_FLOAT,
+ OBJECTIVECTYPE_DOUBLE,
+ OBJECTIVECTYPE_BOOLEAN,
+ OBJECTIVECTYPE_STRING,
+ OBJECTIVECTYPE_DATA,
+ OBJECTIVECTYPE_ENUM,
+ OBJECTIVECTYPE_MESSAGE
+};
+
+string GetCapitalizedType(const FieldDescriptor* field);
+
+ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type);
+
+inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) {
+ return GetObjectiveCType(field->type());
+}
+
+bool IsPrimitiveType(const FieldDescriptor* field);
+bool IsReferenceType(const FieldDescriptor* field);
+
+string GPBValueFieldName(const FieldDescriptor* field);
+string DefaultValue(const FieldDescriptor* field);
+
+string BuildFlagsString(const vector<string>& strings);
+
+string BuildCommentsString(const SourceLocation& location);
+
+bool WriteClassList(string* error);
+void WriteClassNameToClassList(const string& name);
+
+bool InitializeClassWhitelist(string* error);
+bool FilterClass(const string& name);
+
+// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
+// the input into the the expected output.
+class TextFormatDecodeData {
+ public:
+ TextFormatDecodeData() {}
+
+ void AddString(int32_t key, const string& input_for_decode,
+ const string& desired_output);
+ size_t num_entries() const { return entries_.size(); }
+ string Data() const;
+
+ static string DecodeDataForString(const string& input_for_decode,
+ const string& desired_output);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormatDecodeData);
+
+ typedef std::pair<int32_t, string> DataEntry;
+ vector<DataEntry> entries_;
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
new file mode 100644
index 00000000..c9682b08
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
@@ -0,0 +1,242 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2014 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.
+
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/testing/googletest.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+namespace {
+
+TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_RawStrings) {
+ string input_for_decode("abcdefghIJ");
+ string desired_output_for_decode;
+ string expected;
+ string result;
+
+ // Different data, can't transform.
+
+ desired_output_for_decode = "zbcdefghIJ";
+ expected = string("\0zbcdefghIJ\0", 12);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ desired_output_for_decode = "abcdezghIJ";
+ expected = string("\0abcdezghIJ\0", 12);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ // Shortened data, can't transform.
+
+ desired_output_for_decode = "abcdefghI";
+ expected = string("\0abcdefghI\0", 11);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ // Extra data, can't transform.
+
+ desired_output_for_decode = "abcdefghIJz";
+ expected = string("\0abcdefghIJz\0", 13);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+}
+
+TEST(ObjCHelper, TextFormatDecodeData_DecodeDataForString_ByteCodes) {
+ string input_for_decode("abcdefghIJ");
+ string desired_output_for_decode;
+ string expected;
+ string result;
+
+ desired_output_for_decode = "abcdefghIJ";
+ expected = string("\x0A\x0", 2);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ desired_output_for_decode = "_AbcdefghIJ";
+ expected = string("\xCA\x0", 2);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ desired_output_for_decode = "ABCD__EfghI_j";
+ expected = string("\x64\x80\xC5\xA1\x0", 5);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+
+ // Long name so multiple decode ops are needed.
+
+ input_for_decode =
+ "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
+ desired_output_for_decode =
+ "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000";
+ expected = string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9);
+ result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
+ desired_output_for_decode);
+ EXPECT_EQ(expected, result);
+}
+
+TEST(ObjCHelperDeathTest, TextFormatDecodeData_DecodeDataForString_Failures) {
+ // Empty inputs.
+
+ EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("a", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(TextFormatDecodeData::DecodeDataForString("", "a"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+
+ // Null char in the string.
+
+ string str_with_null_char("ab\0c", 4);
+ EXPECT_EXIT(
+ TextFormatDecodeData::DecodeDataForString(str_with_null_char, "def"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+ EXPECT_EXIT(
+ TextFormatDecodeData::DecodeDataForString("def", str_with_null_char),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+}
+
+TEST(ObjCHelper, TextFormatDecodeData_RawStrings) {
+ TextFormatDecodeData decode_data;
+
+ // Different data, can't transform.
+ decode_data.AddString(1, "abcdefghIJ", "zbcdefghIJ");
+ decode_data.AddString(3, "abcdefghIJ", "abcdezghIJ");
+ // Shortened data, can't transform.
+ decode_data.AddString(2, "abcdefghIJ", "abcdefghI");
+ // Extra data, can't transform.
+ decode_data.AddString(4, "abcdefghIJ", "abcdefghIJz");
+
+ EXPECT_EQ(4, decode_data.num_entries());
+
+ uint8_t expected_data[] = {
+ 0x4,
+ 0x1, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
+ 0x3, 0x0, 'a', 'b', 'c', 'd', 'e', 'z', 'g', 'h', 'I', 'J', 0x0,
+ 0x2, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 0x0,
+ 0x4, 0x0, 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 'z', 0x0,
+ };
+ string expected((const char*)expected_data, sizeof(expected_data));
+
+ EXPECT_EQ(expected, decode_data.Data());
+}
+
+TEST(ObjCHelper, TextFormatDecodeData_ByteCodes) {
+ TextFormatDecodeData decode_data;
+
+ decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
+ decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
+ decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
+ decode_data.AddString(4, "abcdefghIJ", "ABCD__EfghI_j");
+ decode_data.AddString(1000,
+ "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000",
+ "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
+
+ EXPECT_EQ(5, decode_data.num_entries());
+
+ uint8_t expected_data[] = {
+ 0x5,
+ // All as is (00 op)
+ 0x1, 0x0A, 0x0,
+ // Underscore, upper + 9 (10 op)
+ 0x3, 0xCA, 0x0,
+ // Upper + 3 (10 op), underscore, upper + 5 (10 op)
+ 0x2, 0x44, 0xC6, 0x0,
+ // All Upper for 4 (11 op), underscore, underscore, upper + 5 (10 op),
+ // underscore, lower + 0 (01 op)
+ 0x4, 0x64, 0x80, 0xC5, 0xA1, 0x0,
+ // 2 byte key: as is + 3 (00 op), underscore, lower + 4 (01 op),
+ // underscore, lower + 3 (01 op), underscore, lower + 1 (01 op),
+ // underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00
+ // op),
+ // underscore, as is + 3 (00 op)
+ 0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
+ };
+ string expected((const char*)expected_data, sizeof(expected_data));
+
+ EXPECT_EQ(expected, decode_data.Data());
+}
+
+TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) {
+ TextFormatDecodeData decode_data;
+
+ // Empty inputs.
+
+ EXPECT_EXIT(decode_data.AddString(1, "", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(decode_data.AddString(1, "a", ""),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+ EXPECT_EXIT(decode_data.AddString(1, "", "a"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got empty string for making TextFormat data, input:");
+
+ // Null char in the string.
+
+ string str_with_null_char("ab\0c", 4);
+ EXPECT_EXIT(
+ decode_data.AddString(1, str_with_null_char, "def"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+ EXPECT_EXIT(
+ decode_data.AddString(1, "def", str_with_null_char),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: got a null char in a string for making TextFormat data, input:");
+
+ // Duplicate keys
+
+ decode_data.AddString(1, "abcdefghIJ", "abcdefghIJ");
+ decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
+ decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
+ EXPECT_EXIT(decode_data.AddString(2, "xyz", "x_yz"),
+ ::testing::KilledBySignal(SIGABRT),
+ "error: duplicate key \\(2\\) making TextFormat data, input:");
+}
+
+} // namespace
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
new file mode 100644
index 00000000..cafdf39d
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
@@ -0,0 +1,161 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// MapFieldGenerator uses RepeatedFieldGenerator as the parent because it
+// provides a bunch of things (no has* methods, comments for contained type,
+// etc.).
+
+namespace {
+
+const char* MapEntryTypeName(const FieldDescriptor* descriptor, bool isKey) {
+ ObjectiveCType type = GetObjectiveCType(descriptor);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ return "Int32";
+ case OBJECTIVECTYPE_UINT32:
+ return "UInt32";
+ case OBJECTIVECTYPE_INT64:
+ return "Int64";
+ case OBJECTIVECTYPE_UINT64:
+ return "UInt64";
+ case OBJECTIVECTYPE_FLOAT:
+ return "Float";
+ case OBJECTIVECTYPE_DOUBLE:
+ return "Double";
+ case OBJECTIVECTYPE_BOOLEAN:
+ return "Bool";
+ case OBJECTIVECTYPE_STRING:
+ return (isKey ? "String" : "Object");
+ case OBJECTIVECTYPE_DATA:
+ return "Object";
+ case OBJECTIVECTYPE_ENUM:
+ return "Enum";
+ case OBJECTIVECTYPE_MESSAGE:
+ return "Object";
+ }
+
+ GOOGLE_LOG(FATAL) << "Can't get here.";
+ return NULL;
+}
+
+} // namespace
+
+MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
+ : RepeatedFieldGenerator(descriptor) {
+ const FieldDescriptor* key_descriptor =
+ descriptor->message_type()->FindFieldByName("key");
+ const FieldDescriptor* value_descriptor =
+ descriptor->message_type()->FindFieldByName("value");
+ value_field_generator_.reset(FieldGenerator::Make(value_descriptor));
+
+ // Pull over some variables_ from the value.
+ variables_["field_type"] = value_field_generator_->variable("field_type");
+ variables_["default"] = value_field_generator_->variable("default");
+ variables_["default_name"] = value_field_generator_->variable("default_name");
+
+ // Build custom field flags.
+ std::vector<string> field_flags;
+ field_flags.push_back("GPBFieldMapKey" + GetCapitalizedType(key_descriptor));
+ // Pull over the current text format custom name values that was calculated.
+ if (variables_["fieldflags"].find("GPBFieldTextFormatNameCustom") !=
+ string::npos) {
+ field_flags.push_back("GPBFieldTextFormatNameCustom");
+ }
+ // Pull over some info from the value's flags.
+ const string& value_field_flags =
+ value_field_generator_->variable("fieldflags");
+ if (value_field_flags.find("GPBFieldHasDefaultValue") != string::npos) {
+ field_flags.push_back("GPBFieldHasDefaultValue");
+ }
+ if (value_field_flags.find("GPBFieldHasEnumDescriptor") != string::npos) {
+ field_flags.push_back("GPBFieldHasEnumDescriptor");
+ }
+ variables_["fieldflags"] = BuildFlagsString(field_flags);
+
+ ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
+ if ((GetObjectiveCType(key_descriptor) == OBJECTIVECTYPE_STRING) &&
+ ((value_objc_type == OBJECTIVECTYPE_STRING) ||
+ (value_objc_type == OBJECTIVECTYPE_DATA) ||
+ (value_objc_type == OBJECTIVECTYPE_MESSAGE))) {
+ variables_["array_storage_type"] = "NSMutableDictionary";
+ } else {
+ string base_name = MapEntryTypeName(key_descriptor, true);
+ base_name += MapEntryTypeName(value_descriptor, false);
+ base_name += "Dictionary";
+ variables_["array_storage_type"] = "GPB" + base_name;
+ }
+}
+
+MapFieldGenerator::~MapFieldGenerator() {}
+
+void MapFieldGenerator::FinishInitialization(void) {
+ RepeatedFieldGenerator::FinishInitialization();
+ // Use the array_comment suport in RepeatedFieldGenerator to output what the
+ // values in the map are.
+ const FieldDescriptor* value_descriptor =
+ descriptor_->message_type()->FindFieldByName("value");
+ ObjectiveCType value_objc_type = GetObjectiveCType(value_descriptor);
+ if ((value_objc_type == OBJECTIVECTYPE_MESSAGE) ||
+ (value_objc_type == OBJECTIVECTYPE_DATA) ||
+ (value_objc_type == OBJECTIVECTYPE_STRING) ||
+ (value_objc_type == OBJECTIVECTYPE_ENUM)) {
+ variables_["array_comment"] =
+ "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
+ } else {
+ variables_["array_comment"] = "";
+ }
+}
+
+void MapFieldGenerator::GenerateFieldDescriptionTypeSpecific(
+ io::Printer* printer) const {
+ // Relay it to the value generator to provide enum validator, message
+ // class, etc.
+ value_field_generator_->GenerateFieldDescriptionTypeSpecific(printer);
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
new file mode 100644
index 00000000..8862dc35
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
@@ -0,0 +1,64 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2015 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class MapFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ public:
+ virtual void FinishInitialization(void);
+ virtual void GenerateFieldDescriptionTypeSpecific(io::Printer* printer) const;
+
+ protected:
+ MapFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~MapFieldGenerator();
+
+ private:
+ scoped_ptr<FieldGenerator> value_field_generator_;
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
new file mode 100644
index 00000000..87e4d0f8
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
@@ -0,0 +1,642 @@
+// 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.
+
+#include <algorithm>
+#include <iostream>
+#include <sstream>
+
+#include <google/protobuf/stubs/hash.h>
+#include <google/protobuf/compiler/objectivec/objectivec_message.h>
+#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
+#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/stubs/stl_util.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/io/coded_stream.h>
+#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/descriptor.pb.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+struct FieldOrderingByNumber {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ return a->number() < b->number();
+ }
+};
+
+int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
+ // The first item in the object structure is our uint32[] for has bits.
+ // We then want to order things to make the instances as small as
+ // possible. So we follow the has bits with:
+ // 1. Bools (1 byte)
+ // 2. Anything always 4 bytes - float, *32, enums
+ // 3. Anything that is always a pointer (they will be 8 bytes on 64 bit
+ // builds and 4 bytes on 32bit builds.
+ // 4. Anything always 8 bytes - double, *64
+ //
+ // Why? Using 64bit builds as an example, this means worse case, we have
+ // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
+ // are wasted before the 4 byte values. Then if we have an odd number of
+ // those 4 byte values, the 8 byte values will be pushed down by 32bits to
+ // keep them aligned. But the structure will end 8 byte aligned, so no
+ // waste on the end. If you did the reverse order, you could waste 4 bytes
+ // before the first 8 byte value (after the has array), then a single
+ // bool on the end would need 7 bytes of padding to make the overall
+ // structure 8 byte aligned; so 11 bytes, wasted total.
+
+ // Anything repeated is a GPB*Array/NSArray, so pointer.
+ if (descriptor->is_repeated()) {
+ return 3;
+ }
+
+ switch (descriptor->type()) {
+ // All always 8 bytes.
+ case FieldDescriptor::TYPE_DOUBLE:
+ case FieldDescriptor::TYPE_INT64:
+ case FieldDescriptor::TYPE_SINT64:
+ case FieldDescriptor::TYPE_UINT64:
+ case FieldDescriptor::TYPE_SFIXED64:
+ case FieldDescriptor::TYPE_FIXED64:
+ return 4;
+
+ // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
+ // depending on the build architecture.
+ case FieldDescriptor::TYPE_GROUP:
+ case FieldDescriptor::TYPE_MESSAGE:
+ case FieldDescriptor::TYPE_STRING:
+ case FieldDescriptor::TYPE_BYTES:
+ return 3;
+
+ // All always 4 bytes (enums are int32s).
+ case FieldDescriptor::TYPE_FLOAT:
+ case FieldDescriptor::TYPE_INT32:
+ case FieldDescriptor::TYPE_SINT32:
+ case FieldDescriptor::TYPE_UINT32:
+ case FieldDescriptor::TYPE_SFIXED32:
+ case FieldDescriptor::TYPE_FIXED32:
+ case FieldDescriptor::TYPE_ENUM:
+ return 2;
+
+ // 1 byte.
+ case FieldDescriptor::TYPE_BOOL:
+ return 1;
+ }
+}
+
+struct FieldOrderingByStorageSize {
+ inline bool operator()(const FieldDescriptor* a,
+ const FieldDescriptor* b) const {
+ // Order by grouping.
+ const int order_group_a = OrderGroupForFieldDescriptor(a);
+ const int order_group_b = OrderGroupForFieldDescriptor(b);
+ if (order_group_a != order_group_b) {
+ return order_group_a < order_group_b;
+ }
+ // Within the group, order by field number (provides stable ordering).
+ return a->number() < b->number();
+ }
+};
+
+struct ExtensionRangeOrdering {
+ bool operator()(const Descriptor::ExtensionRange* a,
+ const Descriptor::ExtensionRange* b) const {
+ return a->start < b->start;
+ }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+ const FieldDescriptor** fields =
+ new const FieldDescriptor* [descriptor->field_count()];
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
+ return fields;
+}
+
+// Sort the fields of the given Descriptor by storage size into a new[]'d
+// array and return it.
+const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
+ const FieldDescriptor** fields =
+ new const FieldDescriptor* [descriptor->field_count()];
+ for (int i = 0; i < descriptor->field_count(); i++) {
+ fields[i] = descriptor->field(i);
+ }
+ sort(fields, fields + descriptor->field_count(),
+ FieldOrderingByStorageSize());
+ return fields;
+}
+} // namespace
+
+MessageGenerator::MessageGenerator(const string& root_classname,
+ const Descriptor* descriptor)
+ : root_classname_(root_classname),
+ descriptor_(descriptor),
+ field_generators_(descriptor),
+ class_name_(ClassName(descriptor_)),
+ sub_content_filtered_(true) {
+ if (FilterClass(class_name_)) {
+ filter_reason_ =
+ string("Message |") + class_name_ + "| was not whitelisted.";
+ }
+ if (!IsFiltered()) {
+ // No need to generate extensions if this message is filtered
+ for (int i = 0; i < descriptor_->extension_count(); i++) {
+ extension_generators_.push_back(
+ new ExtensionGenerator(class_name_, descriptor_->extension(i)));
+ }
+ // No need to oneofs if this message is filtered
+ for (int i = 0; i < descriptor_->oneof_decl_count(); i++) {
+ OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
+ oneof_generators_.push_back(generator);
+ }
+ }
+
+ // We may have enums of this message that are used even if the message
+ // itself is filtered.
+ for (int i = 0; i < descriptor_->enum_type_count(); i++) {
+ EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
+ // The enums are exposed via C functions, so they will dead strip if
+ // not used.
+ sub_content_filtered_ &= false;
+ enum_generators_.push_back(generator);
+ }
+
+ // We may have nested messages that are used even if the message itself
+ // is filtered.
+ for (int i = 0; i < descriptor_->nested_type_count(); i++) {
+ const Descriptor* nested_descriptor = descriptor_->nested_type(i);
+ MessageGenerator* generator =
+ new MessageGenerator(root_classname_, nested_descriptor);
+ // Don't check map entries for being filtered, as they don't directly
+ // generate anything in Objective C. In theory, they only should include
+ // references to other toplevel types, but we still make the generators
+ // to be safe.
+ if (!IsMapEntryMessage(nested_descriptor)) {
+ sub_content_filtered_ &= generator->IsFiltered();
+ }
+ sub_content_filtered_ &= generator->IsSubContentFiltered();
+ nested_message_generators_.push_back(generator);
+ }
+}
+
+MessageGenerator::~MessageGenerator() {
+ STLDeleteContainerPointers(extension_generators_.begin(),
+ extension_generators_.end());
+ STLDeleteContainerPointers(enum_generators_.begin(), enum_generators_.end());
+ STLDeleteContainerPointers(nested_message_generators_.begin(),
+ nested_message_generators_.end());
+ STLDeleteContainerPointers(oneof_generators_.begin(),
+ oneof_generators_.end());
+}
+
+void MessageGenerator::GenerateStaticVariablesInitialization(
+ io::Printer* printer, bool* out_generated) {
+ if (!IsFiltered()) {
+ // Skip extensions if we are filtered.
+ for (vector<ExtensionGenerator*>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(printer, out_generated,
+ false);
+ }
+ }
+
+ // Generating sub messages is perfectly fine though.
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateStaticVariablesInitialization(printer, out_generated);
+ }
+}
+
+void MessageGenerator::DetermineDependencies(set<string>* dependencies) {
+ if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) {
+ dependencies->insert("@class " + class_name_);
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->DetermineDependencies(dependencies);
+ }
+}
+
+void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
+ for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
+ iter != enum_generators_.end(); ++iter) {
+ (*iter)->GenerateHeader(printer);
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateEnumHeader(printer);
+ }
+}
+
+void MessageGenerator::GenerateExtensionRegistrationSource(
+ io::Printer* printer) {
+ if (!IsFiltered()) {
+ for (vector<ExtensionGenerator*>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateRegistrationSource(printer);
+ }
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateExtensionRegistrationSource(printer);
+ }
+}
+
+void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
+ // This a a map entry message, just recurse and do nothing directly.
+ if (IsMapEntryMessage(descriptor_)) {
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateMessageHeader(printer);
+ }
+ return;
+ }
+
+ WriteClassNameToClassList(class_name_);
+
+ if (IsFiltered()) {
+ printer->Print("// $filter_reason$\n\n",
+ "filter_reason", filter_reason_);
+ } else {
+ printer->Print(
+ "#pragma mark - $classname$\n"
+ "\n",
+ "classname", class_name_);
+
+ if (descriptor_->field_count()) {
+ // Even if there are fields, they could be filtered away, so always use
+ // a buffer to confirm we have something.
+ ostringstream fieldnumber_stringstream;
+ {
+ scoped_array<const FieldDescriptor*> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+
+ io::OstreamOutputStream fieldnumber_outputstream(
+ &fieldnumber_stringstream);
+ io::Printer fieldnumber_printer(&fieldnumber_outputstream, '$');
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(sorted_fields[i])
+ .GenerateFieldNumberConstant(&fieldnumber_printer);
+ }
+ fieldnumber_stringstream.flush();
+ }
+ const string& fieldnumber_str = fieldnumber_stringstream.str();
+ if (fieldnumber_str.length()) {
+ printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
+ "classname", class_name_);
+ printer->Indent();
+ printer->Print(fieldnumber_str.c_str());
+ printer->Outdent();
+ printer->Print("};\n\n");
+ }
+ }
+
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->GenerateCaseEnum(printer);
+ }
+
+ string message_comments;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ message_comments = BuildCommentsString(location);
+ } else {
+ message_comments = "";
+ }
+
+ printer->Print(
+ "$comments$@interface $classname$ : GPBMessage\n\n",
+ "classname", class_name_,
+ "comments", message_comments);
+
+ vector<bool> seen_oneofs(descriptor_->oneof_decl_count(), false);
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ const FieldDescriptor* field = descriptor_->field(i);
+ if (field->containing_oneof() != NULL) {
+ const int oneof_index = field->containing_oneof()->index();
+ if (!seen_oneofs[oneof_index]) {
+ seen_oneofs[oneof_index] = true;
+ oneof_generators_[oneof_index]->GeneratePublicCasePropertyDeclaration(
+ printer);
+ }
+ }
+ field_generators_.get(field)
+ .GeneratePropertyDeclaration(printer);
+ }
+
+ printer->Print("@end\n\n");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateCFunctionDeclarations(printer);
+ }
+
+ if (!oneof_generators_.empty()) {
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->GenerateClearFunctionDeclaration(printer);
+ }
+ printer->Print("\n");
+ }
+
+ if (descriptor_->extension_count() > 0) {
+ printer->Print("@interface $classname$ (DynamicMethods)\n\n",
+ "classname", class_name_);
+ for (vector<ExtensionGenerator*>::iterator iter =
+ extension_generators_.begin();
+ iter != extension_generators_.end(); ++iter) {
+ (*iter)->GenerateMembersHeader(printer);
+ }
+ printer->Print("@end\n\n");
+ }
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateMessageHeader(printer);
+ }
+}
+
+void MessageGenerator::GenerateSource(io::Printer* printer) {
+ if (!IsFiltered() && !IsMapEntryMessage(descriptor_)) {
+ printer->Print(
+ "#pragma mark - $classname$\n"
+ "\n",
+ "classname", class_name_);
+
+ printer->Print("@implementation $classname$\n\n",
+ "classname", class_name_);
+
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->GeneratePropertyImplementation(printer);
+ }
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GeneratePropertyImplementation(printer);
+ }
+
+ scoped_array<const FieldDescriptor*> sorted_fields(
+ SortFieldsByNumber(descriptor_));
+ scoped_array<const FieldDescriptor*> size_order_fields(
+ SortFieldsByStorageSize(descriptor_));
+
+ vector<const Descriptor::ExtensionRange*> sorted_extensions;
+ for (int i = 0; i < descriptor_->extension_range_count(); ++i) {
+ sorted_extensions.push_back(descriptor_->extension_range(i));
+ }
+
+ sort(sorted_extensions.begin(), sorted_extensions.end(),
+ ExtensionRangeOrdering());
+
+ size_t num_has_bits = descriptor_->field_count();
+ size_t sizeof_has_storage = (num_has_bits + 31) / 32;
+ // Tell all the fields the oneof base.
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->SetOneofIndexBase(sizeof_has_storage);
+ }
+ field_generators_.SetOneofIndexBase(sizeof_has_storage);
+ // Add an int32 for each oneof to store which is set.
+ sizeof_has_storage += descriptor_->oneof_decl_count();
+
+ printer->Print(
+ "\n"
+ "typedef struct $classname$_Storage {\n"
+ " uint32_t _has_storage_[$sizeof_has_storage$];\n",
+ "classname", class_name_,
+ "sizeof_has_storage", SimpleItoa(sizeof_has_storage));
+ printer->Indent();
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(size_order_fields[i])
+ .GenerateFieldStorageDeclaration(printer);
+ }
+ printer->Outdent();
+
+ printer->Print("} $classname$_Storage;\n\n", "classname", class_name_);
+
+
+ printer->Print(
+ "// This method is threadsafe because it is initially called\n"
+ "// in +initialize for each subclass.\n"
+ "+ (GPBDescriptor *)descriptor {\n"
+ " static GPBDescriptor *descriptor = NULL;\n"
+ " if (!descriptor) {\n");
+
+ bool has_oneofs = oneof_generators_.size();
+ if (has_oneofs) {
+ printer->Print(
+ " static GPBMessageOneofDescription oneofs[] = {\n");
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->GenerateDescription(printer);
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ printer->Print(
+ " };\n");
+ }
+
+ printer->Print(
+ " static GPBMessageFieldDescription fields[] = {\n");
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+ TextFormatDecodeData text_format_decode_data;
+ for (int i = 0; i < descriptor_->field_count(); ++i) {
+ const FieldGenerator& field_generator =
+ field_generators_.get(sorted_fields[i]);
+ field_generator.GenerateFieldDescription(printer);
+ if (field_generator.needs_textformat_name_support()) {
+ text_format_decode_data.AddString(sorted_fields[i]->number(),
+ field_generator.generated_objc_name(),
+ field_generator.raw_field_name());
+ }
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+
+ bool has_enums = enum_generators_.size();
+ if (has_enums) {
+ printer->Print(
+ " };\n"
+ " static GPBMessageEnumDescription enums[] = {\n");
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+ for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
+ iter != enum_generators_.end(); ++iter) {
+ printer->Print("{ .enumDescriptorFunc = $name$_EnumDescriptor },\n",
+ "name", (*iter)->name());
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ }
+
+ bool has_extensions = sorted_extensions.size();
+ if (has_extensions) {
+ printer->Print(
+ " };\n"
+ " static GPBExtensionRange ranges[] = {\n");
+ printer->Indent();
+ printer->Indent();
+ printer->Indent();
+ for (int i = 0; i < sorted_extensions.size(); i++) {
+ printer->Print("{ .start = $start$, .end = $end$ },\n",
+ "start", SimpleItoa(sorted_extensions[i]->start),
+ "end", SimpleItoa(sorted_extensions[i]->end));
+ }
+ printer->Outdent();
+ printer->Outdent();
+ printer->Outdent();
+ }
+
+ map<string, string> vars;
+ vars["classname"] = class_name_;
+ vars["rootclassname"] = root_classname_;
+ vars["oneofs"] = has_oneofs ? "oneofs" : "NULL";
+ vars["oneof_count"] =
+ has_oneofs ? "sizeof(oneofs) / sizeof(GPBMessageOneofDescription)" : "0";
+ vars["enums"] = has_enums ? "enums" : "NULL";
+ vars["enum_count"] =
+ has_enums ? "sizeof(enums) / sizeof(GPBMessageEnumDescription)" : "0";
+ vars["ranges"] = has_extensions ? "ranges" : "NULL";
+ vars["range_count"] =
+ has_extensions ? "sizeof(ranges) / sizeof(GPBExtensionRange)" : "0";
+ vars["wireformat"] =
+ descriptor_->options().message_set_wire_format() ? "YES" : "NO";
+
+ printer->Print(" };\n");
+ if (text_format_decode_data.num_entries() == 0) {
+ printer->Print(
+ vars,
+ " descriptor = [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
+ " rootClass:[$rootclassname$ class]\n"
+ " file:$rootclassname$_FileDescriptor()\n"
+ " fields:fields\n"
+ " fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)\n"
+ " oneofs:$oneofs$\n"
+ " oneofCount:$oneof_count$\n"
+ " enums:$enums$\n"
+ " enumCount:$enum_count$\n"
+ " ranges:$ranges$\n"
+ " rangeCount:$range_count$\n"
+ " storageSize:sizeof($classname$_Storage)\n"
+ " wireFormat:$wireformat$];\n");
+ } else {
+ vars["extraTextFormatInfo"] = CEscape(text_format_decode_data.Data());
+ printer->Print(
+ vars,
+ "#if GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
+ " const char *extraTextFormatInfo = NULL;\n"
+ "#else\n"
+ " static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
+ "#endif // GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
+ " descriptor = [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
+ " rootClass:[$rootclassname$ class]\n"
+ " file:$rootclassname$_FileDescriptor()\n"
+ " fields:fields\n"
+ " fieldCount:sizeof(fields) / sizeof(GPBMessageFieldDescription)\n"
+ " oneofs:$oneofs$\n"
+ " oneofCount:$oneof_count$\n"
+ " enums:$enums$\n"
+ " enumCount:$enum_count$\n"
+ " ranges:$ranges$\n"
+ " rangeCount:$range_count$\n"
+ " storageSize:sizeof($classname$_Storage)\n"
+ " wireFormat:$wireformat$\n"
+ " extraTextFormatInfo:extraTextFormatInfo];\n");
+ }
+ printer->Print(
+ " }\n"
+ " return descriptor;\n"
+ "}\n\n"
+ "@end\n\n");
+
+ for (int i = 0; i < descriptor_->field_count(); i++) {
+ field_generators_.get(descriptor_->field(i))
+ .GenerateCFunctionImplementations(printer);
+ }
+
+ for (vector<OneofGenerator*>::iterator iter = oneof_generators_.begin();
+ iter != oneof_generators_.end(); ++iter) {
+ (*iter)->GenerateClearFunctionImplementation(printer);
+ }
+ }
+
+ for (vector<EnumGenerator*>::iterator iter = enum_generators_.begin();
+ iter != enum_generators_.end(); ++iter) {
+ (*iter)->GenerateSource(printer);
+ }
+
+ for (vector<MessageGenerator*>::iterator iter =
+ nested_message_generators_.begin();
+ iter != nested_message_generators_.end(); ++iter) {
+ (*iter)->GenerateSource(printer);
+ }
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/objectivec_message.h
new file mode 100644
index 00000000..5992d0cf
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message.h
@@ -0,0 +1,103 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/compiler/objectivec/objectivec_oneof.h>
+#include <google/protobuf/stubs/common.h>
+
+namespace google {
+namespace protobuf {
+
+namespace io {
+class Printer; // printer.h
+} // namespace io
+
+namespace compiler {
+namespace objectivec {
+
+class ExtensionGenerator;
+class EnumGenerator;
+
+class MessageGenerator {
+ public:
+ MessageGenerator(const string& root_classname, const Descriptor* descriptor);
+ ~MessageGenerator();
+
+ void GenerateStaticVariablesInitialization(io::Printer* printer,
+ bool* out_generated);
+ void GenerateEnumHeader(io::Printer* printer);
+ void GenerateMessageHeader(io::Printer* printer);
+ void GenerateSource(io::Printer* printer);
+ void GenerateExtensionRegistrationSource(io::Printer* printer);
+ void DetermineDependencies(set<string>* dependencies);
+
+ // This only speaks for this message, not sub message/enums.
+ bool IsFiltered() const { return filter_reason_.length() > 0; }
+ // This message being filtered doesn't effect this, instead it covers if
+ // there are any nested messages or enums.
+ bool IsSubContentFiltered() const { return sub_content_filtered_; }
+
+ private:
+ void GenerateParseFromMethodsHeader(io::Printer* printer);
+
+ void GenerateSerializeOneFieldSource(io::Printer* printer,
+ const FieldDescriptor* field);
+ void GenerateSerializeOneExtensionRangeSource(
+ io::Printer* printer, const Descriptor::ExtensionRange* range);
+
+ void GenerateMessageDescriptionSource(io::Printer* printer);
+ void GenerateDescriptionOneFieldSource(io::Printer* printer,
+ const FieldDescriptor* field);
+
+ const string root_classname_;
+ const Descriptor* descriptor_;
+ FieldGeneratorMap field_generators_;
+ const string class_name_;
+ string filter_reason_;
+ bool sub_content_filtered_;
+ vector<ExtensionGenerator*> extension_generators_;
+ vector<EnumGenerator*> enum_generators_;
+ vector<MessageGenerator*> nested_message_generators_;
+ vector<OneofGenerator*> oneof_generators_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+};
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
new file mode 100644
index 00000000..9c4a4e44
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
@@ -0,0 +1,90 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+void SetMessageVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ const string& message_type = ClassName(descriptor->message_type());
+ (*variables)["type"] = message_type;
+ (*variables)["containing_class"] = ClassName(descriptor->containing_type());
+ (*variables)["storage_type"] = message_type;
+ (*variables)["group_or_message"] =
+ (descriptor->type() == FieldDescriptor::TYPE_GROUP) ? "Group" : "Message";
+
+ (*variables)["typeSpecific_value"] = "GPBStringifySymbol(" + message_type + ")";
+}
+
+} // namespace
+
+MessageFieldGenerator::MessageFieldGenerator(const FieldDescriptor* descriptor)
+ : ObjCObjFieldGenerator(descriptor) {
+ SetMessageVariables(descriptor, &variables_);
+}
+
+MessageFieldGenerator::~MessageFieldGenerator() {}
+
+bool MessageFieldGenerator::WantsHasProperty(void) const {
+ if (descriptor_->containing_oneof() != NULL) {
+ // If in a oneof, it uses the oneofcase instead of a has bit.
+ return false;
+ }
+ // In both proto2 & proto3, message fields have a has* property to tell
+ // when it is a non default value.
+ return true;
+}
+
+RepeatedMessageFieldGenerator::RepeatedMessageFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : RepeatedFieldGenerator(descriptor) {
+ SetMessageVariables(descriptor, &variables_);
+ variables_["array_storage_type"] = "NSMutableArray";
+}
+
+RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
new file mode 100644
index 00000000..a1ac2d39
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
@@ -0,0 +1,71 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class MessageFieldGenerator : public ObjCObjFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+ MessageFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~MessageFieldGenerator();
+ virtual bool WantsHasProperty(void) const;
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
+};
+
+class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+ RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~RepeatedMessageFieldGenerator();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
new file mode 100644
index 00000000..77664c68
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
@@ -0,0 +1,139 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_oneof.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/descriptor.pb.h>
+#include <google/protobuf/stubs/strutil.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+OneofGenerator::OneofGenerator(const OneofDescriptor* descriptor)
+ : descriptor_(descriptor) {
+ variables_["enum_name"] = OneofEnumName(descriptor_);
+ variables_["name"] = OneofName(descriptor_);
+ variables_["capitalized_name"] = OneofNameCapitalized(descriptor_);
+ variables_["raw_index"] = SimpleItoa(descriptor_->index());
+ const Descriptor* msg_descriptor = descriptor_->containing_type();
+ variables_["owning_message_class"] = ClassName(msg_descriptor);
+
+ string comments;
+ SourceLocation location;
+ if (descriptor_->GetSourceLocation(&location)) {
+ comments = BuildCommentsString(location);
+ } else {
+ comments = "";
+ }
+ variables_["comments"] = comments;
+}
+
+OneofGenerator::~OneofGenerator() {}
+
+void OneofGenerator::SetOneofIndexBase(int index_base) {
+ int index = descriptor_->index() + index_base;
+ // Flip the sign to mark it as a oneof.
+ variables_["index"] = SimpleItoa(-index);
+}
+
+void OneofGenerator::GenerateCaseEnum(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "typedef GPB_ENUM($enum_name$) {\n");
+ printer->Indent();
+ printer->Print(
+ variables_,
+ "$enum_name$_GPBUnsetOneOfCase = 0,\n");
+ string enum_name = variables_["enum_name"];
+ for (int j = 0; j < descriptor_->field_count(); j++) {
+ const FieldDescriptor* field = descriptor_->field(j);
+ string field_name = FieldNameCapitalized(field);
+ printer->Print(
+ "$enum_name$_$field_name$ = $field_number$,\n",
+ "enum_name", enum_name,
+ "field_name", field_name,
+ "field_number", SimpleItoa(field->number()));
+ }
+ printer->Outdent();
+ printer->Print(
+ "};\n"
+ "\n");
+}
+
+void OneofGenerator::GeneratePublicCasePropertyDeclaration(
+ io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "$comments$"
+ "@property(nonatomic, readonly) $enum_name$ $name$OneOfCase;\n"
+ "\n");
+}
+
+void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n");
+}
+
+void OneofGenerator::GeneratePropertyImplementation(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "@dynamic $name$OneOfCase;\n");
+}
+
+void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n"
+ " GPBDescriptor *descriptor = [message descriptor];\n"
+ " GPBOneofDescriptor *oneof = descriptor->oneofs_[$raw_index$];\n"
+ " GPBMaybeClearOneof(message, oneof, 0);\n"
+ "}\n");
+}
+
+void OneofGenerator::GenerateDescription(io::Printer* printer) {
+ printer->Print(
+ variables_,
+ "{\n"
+ " .name = \"$name$\",\n"
+ " .index = $index$,\n"
+ "},\n");
+}
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
new file mode 100644
index 00000000..77b7f800
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
@@ -0,0 +1,77 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
+
+#include <string>
+#include <set>
+#include <vector>
+#include <google/protobuf/descriptor.h>
+
+namespace google {
+namespace protobuf {
+namespace io {
+class Printer; // printer.h
+}
+}
+
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class OneofGenerator {
+ public:
+ OneofGenerator(const OneofDescriptor* descriptor);
+ ~OneofGenerator();
+
+ void SetOneofIndexBase(int index_base);
+
+ void GenerateCaseEnum(io::Printer* printer);
+
+ void GeneratePublicCasePropertyDeclaration(io::Printer* printer);
+ void GenerateClearFunctionDeclaration(io::Printer* printer);
+
+ void GeneratePropertyImplementation(io::Printer* printer);
+ void GenerateClearFunctionImplementation(io::Printer* printer);
+ void GenerateDescription(io::Printer* printer);
+
+ private:
+ const OneofDescriptor* descriptor_;
+ map<string, string> variables_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
new file mode 100644
index 00000000..8272c67b
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
@@ -0,0 +1,162 @@
+// 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.
+
+#include <map>
+#include <string>
+
+#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
+#include <google/protobuf/stubs/common.h>
+#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
+#include <google/protobuf/io/printer.h>
+#include <google/protobuf/wire_format.h>
+#include <google/protobuf/wire_format_lite_inl.h>
+#include <google/protobuf/stubs/strutil.h>
+#include <google/protobuf/stubs/substitute.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+using internal::WireFormat;
+using internal::WireFormatLite;
+
+namespace {
+
+const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
+ ObjectiveCType type = GetObjectiveCType(descriptor);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ return "int32_t";
+ case OBJECTIVECTYPE_UINT32:
+ return "uint32_t";
+ case OBJECTIVECTYPE_INT64:
+ return "int64_t";
+ case OBJECTIVECTYPE_UINT64:
+ return "uint64_t";
+ case OBJECTIVECTYPE_FLOAT:
+ return "float";
+ case OBJECTIVECTYPE_DOUBLE:
+ return "double";
+ case OBJECTIVECTYPE_BOOLEAN:
+ return "BOOL";
+ case OBJECTIVECTYPE_STRING:
+ return "NSString";
+ case OBJECTIVECTYPE_DATA:
+ return "NSData";
+ case OBJECTIVECTYPE_ENUM:
+ return "int32_t";
+ case OBJECTIVECTYPE_MESSAGE:
+ return NULL;
+ }
+}
+
+const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) {
+ ObjectiveCType type = GetObjectiveCType(descriptor);
+ switch (type) {
+ case OBJECTIVECTYPE_INT32:
+ return "Int32";
+ case OBJECTIVECTYPE_UINT32:
+ return "UInt32";
+ case OBJECTIVECTYPE_INT64:
+ return "Int64";
+ case OBJECTIVECTYPE_UINT64:
+ return "UInt64";
+ case OBJECTIVECTYPE_FLOAT:
+ return "Float";
+ case OBJECTIVECTYPE_DOUBLE:
+ return "Double";
+ case OBJECTIVECTYPE_BOOLEAN:
+ return "Bool";
+ case OBJECTIVECTYPE_STRING:
+ return ""; // Want NSArray
+ case OBJECTIVECTYPE_DATA:
+ return ""; // Want NSArray
+ case OBJECTIVECTYPE_ENUM:
+ return "Enum";
+ case OBJECTIVECTYPE_MESSAGE:
+ return ""; // Want NSArray
+ }
+}
+
+void SetPrimitiveVariables(const FieldDescriptor* descriptor,
+ map<string, string>* variables) {
+ std::string primitive_name = PrimitiveTypeName(descriptor);
+ (*variables)["type"] = primitive_name;
+ (*variables)["storage_type"] = primitive_name;
+}
+
+} // namespace
+
+PrimitiveFieldGenerator::PrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : SingleFieldGenerator(descriptor) {
+ SetPrimitiveVariables(descriptor, &variables_);
+}
+
+PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
+
+PrimitiveObjFieldGenerator::PrimitiveObjFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : ObjCObjFieldGenerator(descriptor) {
+ SetPrimitiveVariables(descriptor, &variables_);
+ variables_["property_storage_attribute"] = "copy";
+}
+
+PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
+
+RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
+ const FieldDescriptor* descriptor)
+ : RepeatedFieldGenerator(descriptor) {
+ SetPrimitiveVariables(descriptor, &variables_);
+
+ string base_name = PrimitiveArrayTypeName(descriptor);
+ if (base_name.length()) {
+ variables_["array_storage_type"] = "GPB" + base_name + "Array";
+ } else {
+ variables_["array_storage_type"] = "NSMutableArray";
+ }
+}
+
+RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
+
+void RepeatedPrimitiveFieldGenerator::FinishInitialization(void) {
+ RepeatedFieldGenerator::FinishInitialization();
+ if (IsPrimitiveType(descriptor_)) {
+ // No comment needed for primitive types.
+ variables_["array_comment"] = "";
+ }
+}
+
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
new file mode 100644
index 00000000..b3599297
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
@@ -0,0 +1,82 @@
+// 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.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
+
+#include <map>
+#include <string>
+#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class PrimitiveFieldGenerator : public SingleFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+ PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~PrimitiveFieldGenerator();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
+};
+
+class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+ PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~PrimitiveObjFieldGenerator();
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveObjFieldGenerator);
+};
+
+class RepeatedPrimitiveFieldGenerator : public RepeatedFieldGenerator {
+ friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
+
+ protected:
+ RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
+ virtual ~RepeatedPrimitiveFieldGenerator();
+ virtual void FinishInitialization(void);
+
+ private:
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
+};
+
+} // namespace objectivec
+} // namespace compiler
+} // namespace protobuf
+} // namespace google
+
+#endif // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 0e264f54..c0a48cea 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -59,6 +59,10 @@
#include <vector>
#include <google/protobuf/stubs/common.h>
+// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
+#ifdef TYPE_BOOL
+#undef TYPE_BOOL
+#endif // TYPE_BOOL
namespace google {
namespace protobuf {
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index d7100370..5ae36510 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -719,9 +719,9 @@ void protobuf_AddDesc_google_2fprotobuf_2fdescriptor_2eproto() {
"path\030\001 \003(\005B\002\020\001\022\020\n\004span\030\002 \003(\005B\002\020\001\022\030\n\020lead"
"ing_comments\030\003 \001(\t\022\031\n\021trailing_comments\030"
"\004 \001(\t\022!\n\031leading_detached_comments\030\006 \003(\t"
- "BS\n\023com.google.protobufB\020DescriptorProto"
- "sH\001\252\002\'Google.ProtocolBuffers.DescriptorP"
- "rotos", 4685);
+ "BY\n\023com.google.protobufB\020DescriptorProto"
+ "sH\001\242\002\003GPB\252\002\'Google.ProtocolBuffers.Descr"
+ "iptorProtos", 4691);
::google::protobuf::MessageFactory::InternalRegisterGeneratedFile(
"google/protobuf/descriptor.proto", &protobuf_RegisterTypes);
FileDescriptorSet::default_instance_ = new FileDescriptorSet();
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index 375814c9..7099135d 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -43,6 +43,7 @@ package google.protobuf;
option java_package = "com.google.protobuf";
option java_outer_classname = "DescriptorProtos";
option csharp_namespace = "Google.ProtocolBuffers.DescriptorProtos";
+option objc_class_prefix = "GPB";
// descriptor.proto must be optimized for speed because reflection-based
// algorithms don't work during bootstrapping.
diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto
index 59420cc0..0ab970d3 100644
--- a/src/google/protobuf/duration.proto
+++ b/src/google/protobuf/duration.proto
@@ -44,7 +44,7 @@ option csharp_namespace = "Google.ProtocolBuffers";
// two Timestamp values is a Duration and it can be added or subtracted
// from a Timestamp. Range is approximately +-10,000 years.
//
-// Example 1: compute Duration from two Timestamps in pseudo code.
+// Example 1: Compute Duration from two Timestamps in pseudo code.
//
// Timestamp start = ...;
// Timestamp end = ...;
@@ -61,7 +61,7 @@ option csharp_namespace = "Google.ProtocolBuffers";
// duration.nanos += 1000000000;
// }
//
-// Example 2: compute Timestamp from Timestamp + Duration in pseudo code.
+// Example 2: Compute Timestamp from Timestamp + Duration in pseudo code.
//
// Timestamp start = ...;
// Duration duration = ...;
@@ -85,9 +85,9 @@ message Duration {
// Signed fractions of a second at nanosecond resolution of the span
// of time. Durations less than one second are represented with a 0
- // seconds field and a positive or negative nanos field. For durations
- // of one second or more, a non-zero value for the nanos field must be
- // of the same sign as the seconds field. Must be from -999,999,999
+ // `seconds` field and a positive or negative `nanos` field. For durations
+ // of one second or more, a non-zero value for the `nanos` field must be
+ // of the same sign as the `seconds` field. Must be from -999,999,999
// to +999,999,999 inclusive.
int32 nanos = 2;
}
diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto
new file mode 100644
index 00000000..94df0397
--- /dev/null
+++ b/src/google/protobuf/empty.proto
@@ -0,0 +1,50 @@
+// 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.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_multiple_files = true;
+option java_outer_classname = "EmptyProto";
+option java_package = "com.google.protobuf";
+option objc_class_prefix = "GPB";
+
+
+// A generic empty message that you can re-use to avoid defining duplicated
+// empty messages in your APIs. A typical example is to use it as the request
+// or the response type of an API method. For instance:
+//
+// service Foo {
+// rpc Bar(google.protobuf.Empty) returns (google.protobuf.Empty);
+// }
+//
+message Empty {
+
+}
diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto
index 0b98411c..35b1acc3 100644
--- a/src/google/protobuf/field_mask.proto
+++ b/src/google/protobuf/field_mask.proto
@@ -35,6 +35,8 @@ option java_multiple_files = true;
option java_outer_classname = "FieldMaskProto";
option java_package = "com.google.protobuf";
option csharp_namespace = "Google.ProtocolBuffers";
+option objc_class_prefix = "GPB";
+
// `FieldMask` represents a set of symbolic field paths, for example:
//
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
index 9f8703ae..1673e8af 100644
--- a/src/google/protobuf/preserve_unknown_enum_test.cc
+++ b/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -246,8 +246,6 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
protobuf_unittest::TestAllTypes message; // proto2 message
const google::protobuf::Reflection* r = message.GetReflection();
const google::protobuf::Descriptor* d = message.GetDescriptor();
- const google::protobuf::FieldDescriptor* singular_field =
- d->FindFieldByName("optional_nested_enum");
const google::protobuf::FieldDescriptor* repeated_field =
d->FindFieldByName("repeated_nested_enum");
// Add one element to the repeated field so that we can test
@@ -258,6 +256,8 @@ TEST(PreserveUnknownEnumTest, Proto2CatchesUnknownValues) {
r->AddEnum(&message, repeated_field, enum_value);
#ifdef PROTOBUF_HAS_DEATH_TEST
+ const google::protobuf::FieldDescriptor* singular_field =
+ d->FindFieldByName("optional_nested_enum");
// Enum-field integer-based setters GOOGLE_DCHECK-fail on invalid values, in order to
// remain consistent with proto2 generated code.
EXPECT_DEBUG_DEATH({
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index f5f5d3f4..7bfdc40a 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -626,7 +626,7 @@ DEFINE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(inline, MessageLite);
DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES(Message);
-#undef DECLARE_SPECIALIZATIONS_FOR_BASE_CLASSES
+#undef DECLARE_SPECIALIZATIONS_FOR_BASE_PROTO_TYPES
template <>
inline const MessageLite& GenericTypeHandler<MessageLite>::default_instance() {
diff --git a/src/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto
new file mode 100644
index 00000000..2c8a17a8
--- /dev/null
+++ b/src/google/protobuf/source_context.proto
@@ -0,0 +1,46 @@
+// 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.
+syntax = "proto3";
+
+package google.protobuf;
+
+option java_multiple_files = true;
+option java_outer_classname = "SourceContextProto";
+option java_package = "com.google.protobuf";
+option objc_class_prefix = "GPB";
+
+
+// `SourceContext` represents information about the source of a
+// protobuf element, like the file in which it is defined.
+message SourceContext {
+ // The path-qualified name of the .proto file that contained the associated
+ // protobuf element. For example: `"google/protobuf/source.proto"`.
+ string file_name = 1;
+}
diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto
index cfe010c2..cd102731 100644
--- a/src/google/protobuf/struct.proto
+++ b/src/google/protobuf/struct.proto
@@ -36,6 +36,8 @@ option java_multiple_files = true;
option java_outer_classname = "StructProto";
option java_package = "com.google.protobuf";
option csharp_namespace = "Google.ProtocolBuffers";
+option objc_class_prefix = "GPB";
+
// `Struct` represents a structured data value, consisting of fields
// which map to dynamically typed values. In some languages, `Struct`
@@ -56,28 +58,33 @@ message Value {
oneof kind {
// Represents a null value.
NullValue null_value = 1;
+
// Represents a double value.
double number_value = 2;
+
// Represents a string value.
string string_value = 3;
+
// Represents a boolean value.
bool bool_value = 4;
+
// Represents a structured value.
Struct struct_value = 5;
+
// Represents a repeated `Value`.
ListValue list_value = 6;
}
}
+// `ListValue` is a wrapper around a repeated field of values.
+message ListValue {
+ // Repeated field of dynamically typed values.
+ repeated Value values = 1;
+}
+
// `NullValue` is a singleton enumeration to represent the null
// value for the `Value` type union.
enum NullValue {
// Null value.
NULL_VALUE = 0;
}
-
-// `ListValue` is a wrapper around a repeated field of values.
-message ListValue {
- // Repeated field of dynamically typed values.
- repeated Value values = 1;
-}
diff --git a/src/google/protobuf/stubs/atomicops_internals_pnacl.h b/src/google/protobuf/stubs/atomicops_internals_pnacl.h
index b10ac02c..3b314fd0 100644
--- a/src/google/protobuf/stubs/atomicops_internals_pnacl.h
+++ b/src/google/protobuf/stubs/atomicops_internals_pnacl.h
@@ -33,39 +33,197 @@
#ifndef GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
#define GOOGLE_PROTOBUF_ATOMICOPS_INTERNALS_PNACL_H_
+#include <atomic>
+
namespace google {
namespace protobuf {
namespace internal {
+// This implementation is transitional and maintains the original API for
+// atomicops.h. This requires casting memory locations to the atomic types, and
+// assumes that the API and the C++11 implementation are layout-compatible,
+// which isn't true for all implementations or hardware platforms. The static
+// assertion should detect this issue, were it to fire then this header
+// shouldn't be used.
+//
+// TODO(jfb) If this header manages to stay committed then the API should be
+// modified, and all call sites updated.
+typedef volatile std::atomic<Atomic32>* AtomicLocation32;
+static_assert(sizeof(*(AtomicLocation32) nullptr) == sizeof(Atomic32),
+ "incompatible 32-bit atomic layout");
+
+inline void MemoryBarrier() {
+#if defined(__GLIBCXX__)
+ // Work around libstdc++ bug 51038 where atomic_thread_fence was declared but
+ // not defined, leading to the linker complaining about undefined references.
+ __atomic_thread_fence(std::memory_order_seq_cst);
+#else
+ std::atomic_thread_fence(std::memory_order_seq_cst);
+#endif
+}
+
inline Atomic32 NoBarrier_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
- return __sync_val_compare_and_swap(ptr, old_value, new_value);
+ ((AtomicLocation32)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_relaxed,
+ std::memory_order_relaxed);
+ return old_value;
}
-inline void MemoryBarrier() {
- __sync_synchronize();
+inline Atomic32 NoBarrier_AtomicExchange(volatile Atomic32* ptr,
+ Atomic32 new_value) {
+ return ((AtomicLocation32)ptr)
+ ->exchange(new_value, std::memory_order_relaxed);
+}
+
+inline Atomic32 NoBarrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return increment +
+ ((AtomicLocation32)ptr)
+ ->fetch_add(increment, std::memory_order_relaxed);
+}
+
+inline Atomic32 Barrier_AtomicIncrement(volatile Atomic32* ptr,
+ Atomic32 increment) {
+ return increment + ((AtomicLocation32)ptr)->fetch_add(increment);
}
inline Atomic32 Acquire_CompareAndSwap(volatile Atomic32* ptr,
Atomic32 old_value,
Atomic32 new_value) {
- Atomic32 ret = NoBarrier_CompareAndSwap(ptr, old_value, new_value);
+ ((AtomicLocation32)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_acquire,
+ std::memory_order_acquire);
+ return old_value;
+}
+
+inline Atomic32 Release_CompareAndSwap(volatile Atomic32* ptr,
+ Atomic32 old_value,
+ Atomic32 new_value) {
+ ((AtomicLocation32)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_release,
+ std::memory_order_relaxed);
+ return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic32* ptr, Atomic32 value) {
+ ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic32* ptr, Atomic32 value) {
+ ((AtomicLocation32)ptr)->store(value, std::memory_order_relaxed);
MemoryBarrier();
- return ret;
}
inline void Release_Store(volatile Atomic32* ptr, Atomic32 value) {
- MemoryBarrier();
- *ptr = value;
+ ((AtomicLocation32)ptr)->store(value, std::memory_order_release);
+}
+
+inline Atomic32 NoBarrier_Load(volatile const Atomic32* ptr) {
+ return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
}
inline Atomic32 Acquire_Load(volatile const Atomic32* ptr) {
- Atomic32 value = *ptr;
+ return ((AtomicLocation32)ptr)->load(std::memory_order_acquire);
+}
+
+inline Atomic32 Release_Load(volatile const Atomic32* ptr) {
+ MemoryBarrier();
+ return ((AtomicLocation32)ptr)->load(std::memory_order_relaxed);
+}
+
+#if defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+
+typedef volatile std::atomic<Atomic64>* AtomicLocation64;
+static_assert(sizeof(*(AtomicLocation64) nullptr) == sizeof(Atomic64),
+ "incompatible 64-bit atomic layout");
+
+inline Atomic64 NoBarrier_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value,
+ Atomic64 new_value) {
+ ((AtomicLocation64)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_relaxed,
+ std::memory_order_relaxed);
+ return old_value;
+}
+
+inline Atomic64 NoBarrier_AtomicExchange(volatile Atomic64* ptr,
+ Atomic64 new_value) {
+ return ((AtomicLocation64)ptr)
+ ->exchange(new_value, std::memory_order_relaxed);
+}
+
+inline Atomic64 NoBarrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return increment +
+ ((AtomicLocation64)ptr)
+ ->fetch_add(increment, std::memory_order_relaxed);
+}
+
+inline Atomic64 Barrier_AtomicIncrement(volatile Atomic64* ptr,
+ Atomic64 increment) {
+ return increment + ((AtomicLocation64)ptr)->fetch_add(increment);
+}
+
+inline Atomic64 Acquire_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value,
+ Atomic64 new_value) {
+ ((AtomicLocation64)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_acquire,
+ std::memory_order_acquire);
+ return old_value;
+}
+
+inline Atomic64 Release_CompareAndSwap(volatile Atomic64* ptr,
+ Atomic64 old_value,
+ Atomic64 new_value) {
+ ((AtomicLocation64)ptr)
+ ->compare_exchange_strong(old_value,
+ new_value,
+ std::memory_order_release,
+ std::memory_order_relaxed);
+ return old_value;
+}
+
+inline void NoBarrier_Store(volatile Atomic64* ptr, Atomic64 value) {
+ ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
+}
+
+inline void Acquire_Store(volatile Atomic64* ptr, Atomic64 value) {
+ ((AtomicLocation64)ptr)->store(value, std::memory_order_relaxed);
MemoryBarrier();
- return value;
}
+inline void Release_Store(volatile Atomic64* ptr, Atomic64 value) {
+ ((AtomicLocation64)ptr)->store(value, std::memory_order_release);
+}
+
+inline Atomic64 NoBarrier_Load(volatile const Atomic64* ptr) {
+ return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
+}
+
+inline Atomic64 Acquire_Load(volatile const Atomic64* ptr) {
+ return ((AtomicLocation64)ptr)->load(std::memory_order_acquire);
+}
+
+inline Atomic64 Release_Load(volatile const Atomic64* ptr) {
+ MemoryBarrier();
+ return ((AtomicLocation64)ptr)->load(std::memory_order_relaxed);
+}
+
+#endif // defined(GOOGLE_PROTOBUF_ARCH_64_BIT)
+
} // namespace internal
} // namespace protobuf
} // namespace google
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index c3f735a2..37123c7b 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -62,6 +62,14 @@
#include <exception>
#endif
+#if defined(__APPLE__)
+#include <TargetConditionals.h> // for TARGET_OS_IPHONE
+#endif
+
+#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+#include <pthread.h>
+#endif
+
#if defined(_WIN32) && defined(GetMessage)
// Allow GetMessage to be used as a valid method name in protobuf classes.
// windows.h defines GetMessage() as a macro. Let's re-define it as an inline
@@ -157,7 +165,7 @@ std::string LIBPROTOBUF_EXPORT VersionString(int version);
typedef unsigned int uint;
#ifdef _MSC_VER
-typedef __int8 int8;
+typedef signed __int8 int8;
typedef __int16 int16;
typedef __int32 int32;
typedef __int64 int64;
@@ -1158,6 +1166,38 @@ class LIBPROTOBUF_EXPORT MutexLockMaybe {
GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
};
+#if defined(__ANDROID__) || defined(GOOGLE_PROTOBUF_OS_ANDROID) || (defined(TARGET_OS_IPHONE) && TARGET_OS_IPHONE) || defined(GOOGLE_PROTOBUF_OS_IPHONE)
+// Android ndk does not support the __thread keyword very well yet. Here
+// we use pthread_key_create()/pthread_getspecific()/... methods for
+// TLS support on android.
+// iOS also does not support the __thread keyword.
+template<typename T>
+class ThreadLocalStorage {
+ public:
+ ThreadLocalStorage() {
+ pthread_key_create(&key_, &ThreadLocalStorage::Delete);
+ }
+ ~ThreadLocalStorage() {
+ pthread_key_delete(key_);
+ }
+ T* Get() {
+ T* result = static_cast<T*>(pthread_getspecific(key_));
+ if (result == NULL) {
+ result = new T();
+ pthread_setspecific(key_, result);
+ }
+ return result;
+ }
+ private:
+ static void Delete(void* value) {
+ delete static_cast<T*>(value);
+ }
+ pthread_key_t key_;
+
+ GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage);
+};
+#endif
+
} // namespace internal
// We made these internal so that they would show up as such in the docs,
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
index 82d5052e..11bc2b37 100755
--- a/src/google/protobuf/stubs/hash.h
+++ b/src/google/protobuf/stubs/hash.h
@@ -172,6 +172,13 @@ struct hash<const char*> {
}
};
+template<>
+struct hash<bool> {
+ size_t operator()(bool x) const {
+ return static_cast<size_t>(x);
+ }
+};
+
template <typename Key, typename Data,
typename HashFcn = hash<Key>,
typename EqualKey = std::equal_to<Key>,
@@ -204,7 +211,7 @@ struct hash<string> {
static const size_t bucket_size = 4;
static const size_t min_buckets = 8;
- inline size_t operator()(const string& a, const string& b) const {
+ inline bool operator()(const string& a, const string& b) const {
return a < b;
}
};
@@ -222,7 +229,7 @@ struct hash<pair<First, Second> > {
static const size_t bucket_size = 4;
static const size_t min_buckets = 8;
- inline size_t operator()(const pair<First, Second>& a,
+ inline bool operator()(const pair<First, Second>& a,
const pair<First, Second>& b) const {
return a < b;
}
diff --git a/src/google/protobuf/stubs/platform_macros.h b/src/google/protobuf/stubs/platform_macros.h
index 1ff09b83..2ce7fc8f 100644
--- a/src/google/protobuf/stubs/platform_macros.h
+++ b/src/google/protobuf/stubs/platform_macros.h
@@ -95,12 +95,18 @@ GOOGLE_PROTOBUF_PLATFORM_ERROR
#if defined(__APPLE__)
#define GOOGLE_PROTOBUF_OS_APPLE
+#include <TargetConditionals.h>
+#if TARGET_OS_IPHONE
+#define GOOGLE_PROTOBUF_OS_IPHONE
+#endif
#elif defined(__native_client__)
#define GOOGLE_PROTOBUF_OS_NACL
#elif defined(sun)
#define GOOGLE_PROTOBUF_OS_SOLARIS
#elif defined(_AIX)
#define GOOGLE_PROTOBUF_OS_AIX
+#elif defined(__ANDROID__)
+#define GOOGLE_PROTOBUF_OS_ANDROID
#endif
#undef GOOGLE_PROTOBUF_PLATFORM_ERROR
diff --git a/src/google/protobuf/stubs/type_traits.h b/src/google/protobuf/stubs/type_traits.h
index b58cae3f..36a8f3b1 100644
--- a/src/google/protobuf/stubs/type_traits.h
+++ b/src/google/protobuf/stubs/type_traits.h
@@ -73,6 +73,10 @@ struct is_base_of {
typedef char (&yes)[1];
typedef char (&no)[2];
+ // BEGIN GOOGLE LOCAL MODIFICATION -- check is a #define on Mac.
+ #undef check
+ // END GOOGLE LOCAL MODIFICATION
+
static yes check(const B*);
static no check(const void*);
diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc
index d72fa5c0..5f6a199a 100644
--- a/src/google/protobuf/testing/googletest.cc
+++ b/src/google/protobuf/testing/googletest.cc
@@ -65,6 +65,7 @@ namespace protobuf {
#endif
string TestSourceDir() {
+#ifndef GOOGLE_THIRD_PARTY_PROTOBUF
#ifdef _MSC_VER
// Look for the "src" directory.
string prefix = ".";
@@ -88,6 +89,9 @@ string TestSourceDir() {
return result;
}
#endif
+#else
+ return "third_party/protobuf/src";
+#endif // GOOGLE_THIRD_PARTY_PROTOBUF
}
namespace {
diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto
index 94386de1..381ff997 100644
--- a/src/google/protobuf/timestamp.proto
+++ b/src/google/protobuf/timestamp.proto
@@ -36,6 +36,8 @@ option java_multiple_files = true;
option java_outer_classname = "TimestampProto";
option java_package = "com.google.protobuf";
option csharp_namespace = "Google.ProtocolBuffers";
+option objc_class_prefix = "GPB";
+
// A Timestamp represents a point in time independent of any time zone
// or calendar, represented as seconds and fractions of seconds at
@@ -46,15 +48,16 @@ option csharp_namespace = "Google.ProtocolBuffers";
// table is needed for interpretation. Range is from
// 0001-01-01T00:00:00Z to 9999-12-31T23:59:59.999999999Z.
// By restricting to that range, we ensure that we can convert to
-// and from RFC 3339 date strings. (See https://www.ietf.org/rfc/rfc3339.txt.)
+// and from RFC 3339 date strings.
+// See [https://www.ietf.org/rfc/rfc3339.txt](https://www.ietf.org/rfc/rfc3339.txt).
//
-// Example 1: compute Timestamp from POSIX `time()`.
+// Example 1: Compute Timestamp from POSIX `time()`.
//
// Timestamp timestamp;
// timestamp.set_seconds(time(NULL));
// timestamp.set_nanos(0);
//
-// Example 2: compute Timestamp from POSIX `gettimeofday()`.
+// Example 2: Compute Timestamp from POSIX `gettimeofday()`.
//
// struct timeval tv;
// gettimeofday(&tv, NULL);
@@ -63,7 +66,7 @@ option csharp_namespace = "Google.ProtocolBuffers";
// timestamp.set_seconds(tv.tv_sec);
// timestamp.set_nanos(tv.tv_usec * 1000);
//
-// Example 3: compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
+// Example 3: Compute Timestamp from Win32 `GetSystemTimeAsFileTime()`.
//
// FILETIME ft;
// GetSystemTimeAsFileTime(&ft);
@@ -75,14 +78,14 @@ option csharp_namespace = "Google.ProtocolBuffers";
// timestamp.set_seconds((INT64) ((ticks / 10000000) - 11644473600LL));
// timestamp.set_nanos((INT32) ((ticks % 10000000) * 100));
//
-// Example 4: compute Timestamp from Java `System.currentTimeMillis()`.
+// Example 4: Compute Timestamp from Java `System.currentTimeMillis()`.
//
// long millis = System.currentTimeMillis();
//
// Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
// .setNanos((int) ((millis % 1000) * 1000000)).build();
//
-// Example 5: compute Timestamp from Python `datetime.datetime`.
+// Example 5: Compute Timestamp from Python `datetime.datetime`.
//
// now = datetime.datetime.utcnow()
// seconds = int(time.mktime(now.timetuple()))
diff --git a/src/google/protobuf/type.proto b/src/google/protobuf/type.proto
new file mode 100644
index 00000000..ace5d995
--- /dev/null
+++ b/src/google/protobuf/type.proto
@@ -0,0 +1,197 @@
+// 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.
+syntax = "proto3";
+
+package google.protobuf;
+
+import "google/protobuf/any.proto";
+import "google/protobuf/source_context.proto";
+
+option java_multiple_files = true;
+option java_outer_classname = "TypeProto";
+option java_package = "com.google.protobuf";
+option objc_class_prefix = "GPB";
+
+
+// A light-weight descriptor for a proto message type.
+message Type {
+ // The fully qualified message name.
+ string name = 1;
+
+ // The list of fields.
+ repeated Field fields = 2;
+
+ // The list of oneof definitions.
+ // The list of oneofs declared in this Type
+ repeated string oneofs = 3;
+
+ // The proto options.
+ repeated Option options = 4;
+
+ // The source context.
+ SourceContext source_context = 5;
+}
+
+// Field represents a single field of a message type.
+message Field {
+ // Kind represents a basic field type.
+ enum Kind {
+ // Field type unknown.
+ TYPE_UNKNOWN = 0;
+
+ // Field type double.
+ TYPE_DOUBLE = 1;
+
+ // Field type float.
+ TYPE_FLOAT = 2;
+
+ // Field type int64.
+ TYPE_INT64 = 3;
+
+ // Field type uint64.
+ TYPE_UINT64 = 4;
+
+ // Field type int32.
+ TYPE_INT32 = 5;
+
+ // Field type fixed64.
+ TYPE_FIXED64 = 6;
+
+ // Field type fixed32.
+ TYPE_FIXED32 = 7;
+
+ // Field type bool.
+ TYPE_BOOL = 8;
+
+ // Field type string.
+ TYPE_STRING = 9;
+
+ // Field type message.
+ TYPE_MESSAGE = 11;
+
+ // Field type bytes.
+ TYPE_BYTES = 12;
+
+ // Field type uint32.
+ TYPE_UINT32 = 13;
+
+ // Field type enum.
+ TYPE_ENUM = 14;
+
+ // Field type sfixed32.
+ TYPE_SFIXED32 = 15;
+
+ // Field type sfixed64.
+ TYPE_SFIXED64 = 16;
+
+ // Field type sint32.
+ TYPE_SINT32 = 17;
+
+ // Field type sint64.
+ TYPE_SINT64 = 18;
+ }
+
+ // Cardinality represents whether a field is optional, required, or
+ // repeated.
+ enum Cardinality {
+ // The field cardinality is unknown. Typically an error condition.
+ CARDINALITY_UNKNOWN = 0;
+
+ // For optional fields.
+ CARDINALITY_OPTIONAL = 1;
+
+ // For required fields. Not used for proto3.
+ CARDINALITY_REQUIRED = 2;
+
+ // For repeated fields.
+ CARDINALITY_REPEATED = 3;
+ }
+
+ // The field kind.
+ Kind kind = 1;
+
+ // The field cardinality, i.e. optional/required/repeated.
+ Cardinality cardinality = 2;
+
+ // The proto field number.
+ int32 number = 3;
+
+ // The field name.
+ string name = 4;
+
+ // The type URL (without the scheme) when the type is MESSAGE or ENUM,
+ // such as `type.googleapis.com/google.protobuf.Empty`.
+ string type_url = 6;
+
+ // Index in Type.oneofs. Starts at 1. Zero means no oneof mapping.
+ int32 oneof_index = 7;
+
+ // Whether to use alternative packed wire representation.
+ bool packed = 8;
+
+ // The proto options.
+ repeated Option options = 9;
+}
+
+// Enum type definition.
+message Enum {
+ // Enum type name.
+ string name = 1;
+
+ // Enum value definitions.
+ repeated EnumValue enumvalue = 2;
+
+ // Proto options for the enum type.
+ repeated Option options = 3;
+
+ // The source context.
+ SourceContext source_context = 4;
+}
+
+// Enum value definition.
+message EnumValue {
+ // Enum value name.
+ string name = 1;
+
+ // Enum value number.
+ int32 number = 2;
+
+ // Proto options for the enum value.
+ repeated Option options = 3;
+}
+
+// Proto option attached to messages/fields/enums etc.
+message Option {
+ // Proto option name.
+ string name = 1;
+
+ // Proto option value.
+ Any value = 2;
+}
diff --git a/src/google/protobuf/unittest_drop_unknown_fields.proto b/src/google/protobuf/unittest_drop_unknown_fields.proto
index 1bb168f2..1b35fad0 100644
--- a/src/google/protobuf/unittest_drop_unknown_fields.proto
+++ b/src/google/protobuf/unittest_drop_unknown_fields.proto
@@ -31,6 +31,7 @@
syntax = "proto3";
package unittest_drop_unknown_fields;
+option objc_class_prefix = "DropUnknowns";
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto
index 5214247e..24e6828f 100644
--- a/src/google/protobuf/unittest_preserve_unknown_enum.proto
+++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto
@@ -31,6 +31,7 @@
syntax = "proto3";
package proto3_preserve_unknown_enum_unittest;
+option objc_class_prefix = "UnknownEnums";
option csharp_namespace = "Google.ProtocolBuffers.TestProtos";
diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto
index 28657fbf..a13e6edb 100644
--- a/src/google/protobuf/wrappers.proto
+++ b/src/google/protobuf/wrappers.proto
@@ -41,6 +41,8 @@ option java_multiple_files = true;
option java_outer_classname = "WrappersProto";
option java_package = "com.google.protobuf";
option csharp_namespace = "Google.ProtocolBuffers";
+option objc_class_prefix = "GPB";
+
// Wrapper message for double.
message DoubleValue {